How to determine the MATLAB version when compiling C/C++ mex files

11 vues (au cours des 30 derniers jours)
Oliver Woodford
Oliver Woodford le 16 Avr 2015
Commenté : James Tursa le 4 Juin 2018
MATLAB's C/C++ mex interface changes from time to time, with new releases of MATLAB. Functionality can be added, removed or changed. In order to write a C/C++ mex file which can be compiled by different versions of MATLAB, it might be necessary to have separate code for these different versions, selected using pre-processor macros. To do this, there needs to be a #define in mex.h which states the MATLAB version. Is there such a #define, and if so, what is it called?

Réponse acceptée

Jan
Jan le 16 Avr 2015
Modifié(e) : Jan le 16 Avr 2015
This has been a problem for a long time now. And even if modern Matlab versions define the constant MX_API_VER, this is not defined in older versions.
I'm using a Matlab-function to call mex, which defines:
matlabV = [100, 1] * sscanf(version, '%d.%d', 2);
Args = {sprintf('-DMATLABVER=%d', matlabV)};
Then the constant MATLABVER is e.g. 802 for Matlab 8.02.
  3 commentaires
Jan
Jan le 16 Avr 2015
I add the function "InstallMex.m" to all of my FEX submission, such that at least only one installation script is required. But is has 281 lines of code and need some dosumentation also, and as usual it will not be free of bugs.
It is fine that Matlab 2015 seems to handle a missing "mex setup" automatically.
Oliver Woodford
Oliver Woodford le 16 Avr 2015
Similarly I have my own compile script, which currently stands at 469 sloc :p

Connectez-vous pour commenter.

Plus de réponses (3)

James Tursa
James Tursa le 17 Avr 2015
After reconsidering the fact that I no longer have access to the many MATLAB versions that I used to (changed jobs), I realize that I will never be able to fully test the macro. So I will go ahead and post it here. This macro could most likely be simplified by leveraging the emlrt.h file better, but I don't have the multitude of versions to check anymore so I will just leave it as is for now. If anyone finds versions that don't work you can contact me and maybe we can fix things up.
/* MATLAB_VERSION.h */
/*************************************************************************************
*
* MATLAB (R) is a trademark of The Mathworks (R) Corporation
*
* Filename: MATLAB_VERSION.h
* Programmer: James Tursa
* Version: 1.00
* Date: March 21, 2012
* Copyright: (c) 2012 by James Tursa, All Rights Reserved
*
* This code uses the BSD License:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the distribution
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* MATLAB_VERSION.h is an include file that determines, at compile time, what
* version of MATLAB is being used for the compilation. It has been tested to
* work under R2006a - R2011b, 32-bit Windows. It may work under other versions
* but I don't have access to test them. If you do run into any problems on
* any versions, please e-mail me and let me know so that I can update this
* file. The ultimate goal is to have one file that works across all platforms
* and MATLAB versions (within reason).
*
* Usage: Simply include this file at the top of your code (usually after you
* have already included mex.h or engine.h) and you will get a macro defined
* called MATLAB_VERSION that will contain an integer representation of the
* MATLAB version that is being used for the compile:
*
* 0x2006a = R2006a or earlier
* 0x2006b = R2006b
* 0x2007a = R2007a
* 0x2007b = R2007b
* 0x2008a = R2008a
* 0x2008b = R2008b
* 0x2009a = R2009a
* 0x2009b = R2009b
* 0x2010a = R2010a
* 0x2010b = R2010b
* 0x2011a = R2011a
* 0x2011b = R2011b
* :
* etc
*
* I don't have access to versions earlier than R2006a, so I don't yet have
* logic to differentiate those versions. If you can come up with something
* please let me know. Thanks.
*
* Relies on macros that are defined in matrix.h, tmwtypes.h, blas.h, emlrt.h,
* lapack.h (you don't have to explicitly include them since this header will
* include them if necessary). Also, this macro can essentially be disabled
* if the macro MATLAB_VERSION has already been defined (e.g., by using the
* -DMATLAB_VERSION=blahblah option on the mex command line).
*
* The purpose of knowing the MATLAB version at compile time is so that your
* code can make intelligent decisions with regards to which API functions
* are available (e.g., mxGetProperty and mxSetProperty) for linking. That
* way you can either write substitude functions, dummy stub functions, or
* whatever makes sense for your application, and use #if tests on the value
* of MATLAB_VERSION to determine which code to include at compile time.
*
* Change Log:
* 2012/Mar/21 --> 1.00, Initial Release
*
****************************************************************************/
#if !defined(MATLAB_VERSION)
#if !defined(MWSIZE_MAX)
# define MATLAB_VERSION 0x2006a /* R2006a or earlier */
#elif MX_API_VER < 0x07040000
# define MATLAB_VERSION 0x2006b /* R2006b */
#elif !defined(FMT_PTRDIFF_T)
# define MATLAB_VERSION 0x2007a /* R2007a */
#elif !defined(CUINT64_T)
# define MATLAB_VERSION 0x2007b /* R2007b */
#elif defined(mxSetLogical)
# define MATLAB_VERSION 0x2008a /* R2008a */
#else
# if !defined(blas_h)
# include "blas.h"
# endif
# if !defined(lapack_h)
# include "lapack.h"
# endif
# if !defined(MATHWORKS_MATRIX_MATRIX_PUB_FWD_H)
# if defined(CHAR16_T)
# if !defined(COMPLEX_TYPES)
# define MATLAB_VERSION 0x2008b /* R2008b */
# elif !defined(cgeqr2p)
# define MATLAB_VERSION 0x2010b /* R2010b */
# else
# define MATLAB_VERSION 0x2011a /* R2011a */
# endif
# else
# include "emlrt.h"
# define MATLAB_VERSION EMLRT_VERSION_INFO /* R2011b or later */
# endif
# else
# if !defined(COMPLEX_TYPES)
# define MATLAB_VERSION 0x2009a /* R2009a */
# elif !defined(cgbequb)
# define MATLAB_VERSION 0x2009b /* R2009b */
# else
# define MATLAB_VERSION 0x2010a /* R2010a */
# endif
# endif
#endif
#endif /* if !defined(MATLAB_VERSION) */

James Tursa
James Tursa le 16 Avr 2015
Modifié(e) : James Tursa le 16 Avr 2015
mxCreateUninitNumericMatrix has been in the libraries for many years as an exported function, at least as far back as R2006 or so. It just wasn't an officially supported function until recently so the prototype was not included in mex.h. All you have to do to use it in older versions of MATLAB is include the prototype manually in your code. E.g.
mxArray *mxCreateUninitNumericMatrix(mwSize m, mwSize n, mxClassID classid,
mxComplexity ComplexFlag);
There is also a related library function, mxCreateUninitNumericArray, but that was not available in the libraries until R2008b. Again, to use it in R2008b or later simply include the prototype:
mxArray *mxCreateUninitNumericArray(mwSize ndim, const mwSize *dims,
mxClassID classid, mxComplexity ComplexFlag);
If you need the mxCreateUninitNumericArray capability before R2008b, then you can create your own function using mxCreateUninitNumericMatrix in the background and setting the dimensions manually. E.g.,
/* myCreateUninitNumericArray ----------------------------------------- */
/* */
/* Creates uninitialized array using above function. Essentially, this */
/* is a replacement for mxCreateUninitNumericArray, which is only */
/* available for R2008b and later. For two dimensions just call the */
/* mxCreateUninitNumericMatrix function directly. For more than two */
/* dimensions, first multiply all the dimensions to get a single value, */
/* pass that to mxCreateUninitNumericMatrix, then set the dimensions of */
/* the result to the actual desired dimensions. */
/* Programmer: James Tursa */
mxArray *myCreateUninitNumericArray(mwSize ndim, const mwSize *dims,
mxClassID classid, mxComplexity ComplexFlag)
{
mxArray *mx;
mwSize i, m, n;
if( ndim <= 0 ) {
mx = mxCreateUninitNumericMatrix(0,0,classid,ComplexFlag);
} else if( ndim == 1 ) {
mx = mxCreateUninitNumericMatrix(dims[0],1,classid,ComplexFlag);
} else if( ndim == 2 ) {
mx = mxCreateUninitNumericMatrix(dims[0],dims[1],classid,ComplexFlag);
} else {
m = 1;
for( i=0; i<ndim; i++ ) {
n = m;
m *= dims[i];
if( dims[i] && n != m / dims[i] ) { /* Check for overflow */
mexErrMsgTxt("Maximum variable size allowed by the program is exceeded.");
}
}
mx = mxCreateUninitNumericMatrix(m,1,classid,ComplexFlag);
if( mxSetDimensions(mx,dims,ndim) ) {
mxDestroyArray(mx);
mx = NULL;
}
}
return mx;
}
For examples of using these functions, see this FEX submission:
If you are just concerned about R2015a or later, you might try this:
#include "emlrt.h"
#ifdef EMLRT_VERSION_INFO
#if EMLRT_VERSION_INFO < 0x2015a
// version is R2014b or earlier
#else
// version is R2015a or later
#endif
#else
// version is R2014b or earlier
#endif
I don't know how far back the file emlrt.h is available, however, so I am not sure how far back this will work.
I did write a C macro at one time that can discern the exact MATLAB version the code is being compiled under. I will try to find that and post it.
UPDATE: I did find a version of this C macro that I wrote in 2012. However, looking it over I realize I never finished testing it for later versions so never published it. So, for now at least, I will not post it here.

Oliver Woodford
Oliver Woodford le 16 Avr 2015
matrix.h contains the following:
#define MX_API_VER 0x07040000
  1 commentaire
Oliver Woodford
Oliver Woodford le 16 Avr 2015
This number is the same in R2014a and R2015a. However, R2015a introduces a new function, mxCreateUninitNumericMatrix(). If I wanted to use this function, but also support MATLAB versions before R2015a, this #define wouldn't be of help, sadly.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Deploy to C++ Applications Using mwArray API (C++03) dans Help Center et File Exchange

Produits

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by