H2MEX : Matlab MEX Wrapper generator
H2MEX is a program that gernerates automatically the C++ source of an Matlab interface file (MEX file) from header file (the .h file).
The Header file format is a pure C format, It’s extended with some
modifiers that allows to H2MEX to understand the exact task of a C routine.
The generated source (MEX file source) could be compiled without any
modification to create a DLL which is callable from Matlab.
H2MEX is developped by Alaa Makdissi. It’s based on the Matwrap package coded by Gary Holt
H2mex is Freeware.
You download it here H2MEX.EXE
Usage :
h2mex inputfile.h -o output.cpp [-outdir DirectoryName]
where :
-
inputfile.h is an input header file that contains a description of the functions to be wrapped
-
output.cpp is the name of the file to be generated by h2mex
-
The optional -outdir DirectoryName indicates to h2mex to put the generated m files in the directory DirectoryName.
H2MEX Documentations
Most (if not all) of this text is copied (with permission) from the matwraper script written by Gary Holt.
It you have perl installed in your computer then you should use the matwrap package because it has more options and supports more languges than the h2mex program.
Who needs to use this program ?
suppose you have some functions defined in an .h file, like this:
float fiddle(double arg);
double tweedle(int x, char *name);
You can access these directly from MATLAB by using the following:
>>!h2mex fiddle.h -o myfuncs_wrap.c -outdir c:mymfiles
>>mex -v myfuncs_wrap.c
Then, in MATLAB, you can do the following:
y = tweedle(3, 'Hello, world');
A = fiddle([3, 4; 5, 6];
Note especially the last statement, where instead of passing a scalar as the argument, we pass a matrix. The c function fiddle() is called repeatedly on each element of the matrix and the result is returned as a 2×2 matrix.
Floats, doubles, char *, integer, unsigned, and pointers to structures may be used as arugments. Function pointers are not currently supported in any form. C++ operator definitions are not supported either.
C++ classes
You can access public member functions and simple public data members of classes. For example,
class ABC {
public: ABC(int constructor_arg);
void do_something(float number, int idx);
double x;
};
From MATLAB , you would access this structure like this:
ABC_ptr = ABC_new(3); % Call the constructor and return a pointer.
ABC_do_something(ABC_ptr, pi, 4); % Call the member function.
abc_x = ABC_get_x(ABC_ptr); % Get the value of a data member.
ABC_set_x(ABC_ptr, 3.4); % Set the data member.
ABC_delete(ABC_ptr); % Discard the structure.
the same thing will work for C structs–the only difference is that they have only data members and no member functions.
-
- Only public members are accessible from matlab.
- Operator overloading and function overloading are not supported.
- Function pointers are not supported.
Arrays
You can also call functions that take arrays of data, provided that they accept the arrays in a standard format. For example, suppose you want to use the pgplot distribution to make graphs. The following function generates a histogram of data:
void cpgbin(int nbin, const float *x, const float *data, Logical center);
Here x[] are the abscissae values and data[] are the data values. If you add to your .h file a simple statement indicating the dimensions of the matrices, like this:
//%input x(nbin), data(nbin)
then from MATLAB, you can call this function like this:
cpgbin(X, Data, 1)
where X and Data are vectors. The nbin argument is determined from the length of the X and Data vectors automatically (and the wrapper generator makes sure they are of the same length!).
This will also work with multidimensional arrays, provided that the function expects the array to be a single one-dimensional array which is really the concatenation of the columns of the two-dimensional array.(This is normal for Fortran programs.).
The first array dimension varies the fastest, the second the next fastest, etc. (This is column major order, as in Fortran, not row-major order, as in C. Most matlab-like languages use the Fortran convention. Tela is an exception.)
You may only use variable name or a constant for the array dimension. You can also use expressions like 2*nbin or 2*nbin+1. If the expression is sufficiently simple, the wrapper generator will determine the values of any integer values (like nbin in this example) from the dimension of the input arrays, so they do not have to be specified as an argument.
INPUT FILES
Input files are designed to be your ordinary .h files, so your wrapper and your C++ sources are never out of date. In general, the wrapper generator does the obvious thing with each different kind of type. For example, consider the function declaration:
double abcize(float a, int b, char *c, SomeClass *d);
This will pass a single-precision floating point number as argument a. An integer is passed as argument b (probably converted from a double precision value). A null-terminated string is passed as argument c. The argument d must be a pointer value which was returned by another function.
Vectorization is automatically performed, so that if you pass a matrix of m by n inputs as argument a and arguments b and c as either scalars or m by n matrices, then the function will be called m*n times and the result will be an m by n matrix. By default, a function is vectorized if it has both inputs and outputs (see under //%vectorize below). char * arguments are not vectorized.
Passing arguments by reference is handled in the expected way. For example, given the declaration
void fortran_sub(double *inarg1, float *inarg2);
pointers to double and single precision numbers will be passed to the subroutine instead of the numbers themselves.
This creates an ambiguity for the type char *. For example, consider the following two functions:
void f1(char *a); void f2(unsigned char *b);
H2mex assumes that the function f1 is passed a null terminated string, despite the fact that the argument a could be a pointer to a buffer where f1 returns a character. Although this situation can be disambiguated with proper use of the const qualifier, H2mex treats char * and const char * as identical since many programs don’t use const properly. H2mex assumes, however, that unsigned char * is not a null terminated string but an unsigned char variable passed by reference. You can also force it to interpret char * as a signed char passed by reference by specifying the qualifier //%input a(1)(see below).
If you want to pass arguments as arrays, or if there are outputs other than the return value of the function, you must declare these explicitly using the //%input or //%output qualifiers. All qualifiers follow the definition of the function (after the ; or the closing } if it is an inline function).
Valid qualifiers are :
- //%novectorize_type type1, type2, ...
Specifies that all arguments of the given types should not be vectorized even if it is possible. This could be useful if you have a class which there will be only one copy of, so it is pointless to vectorize. (This qualifier may be present anywhere in the file.)
Following the definition of a global function or member function, directs H2mex not to try to vectorize the function. For some functions, vectorization simply doesn’t make sense. By default, H2mex won’t vectorize a function if it has no output arguments or no input arguments.
Following the definition of a global function or member function, directs H2mex to vectorize the function. By default, H2mex won’t vectorize a function if it has no output arguments or no input arguments. This is normally what you want, but but sometimes it makes sense to vectorize a function with no output arguments.
Don’t wrap this function. It will therefore not be callable directly from your scripting language.
Specify a different name for the function when it is invoked from the scripting language.
- //%input argname(dim1, dim2, ...), argname(dim)
Following the declaration of a global function or member function, declares the dimensions of the input arguments with the given name. This declaration must immediately follow the prototype of the function. Dimension strings may contain any arbitrary C expression. If the expression is sufficiently simple, e.g., "n" or "n+1" or "2*n", and if the expression includes another argument to the function ("n" in this case), then the other argument will be calculated from the dimensions of the input variable and need not be specified as an argument in the scripting language.
For example, if you have a function which is declared like this:
void myfunc(int n, double *x, double *y);
//%input x(3*n+4) //%output y(n*(n+1)/2)
n would be calculated from the dimension of the variable x and then used to compute the size of the output array. So you would call the function like this:
>>y = myfunc(x)
On the other hand, if you had a specification like this:
void return_diag(int n, double *x, double *y);
//%input x(n*(n+1)/2) //%output y(n)
then n will have to be explicitly specified because it is too difficult to calculate:
>>y = myfunc(n, x)
- //%modify argname(dim1, dim2, ...), argname(dim1)
- //%output argname(dim1, dim2, ...), argname(dim1)
Same as //%input except that this also tags the variables as modify or output variables. If you don’t specify a dimension expression (e.g., "//%output x") then the variable is tagged as a scalar output variable. (This is the proper way to tell H2mex to make an argument an output argument.)