Reputation: 1356
I need to call a C++ non-member function from MATLAB 2016. MATLAB did not support C++ MEX until 2018, so this poses an issue.
I am doing this in Windows under mingw64.
To get around this, I attempted to make a C file with a MEX wrapper, with the C implementation purely just calling the C++ function using a shared header file with extern "C" based on some advice online.
However, I am very new to MATLAB, calling C++ from C and some other concepts here. So nothing compiles properly whatsoever.
Any advice on properly approaching this is greatly appreciated.
The header file myFunc.h:
#ifndef CPP_H
#define CPP_H
#ifdef __cplusplus
void myFunc(const std::vector<myStruct>& a,
const std::vector<myStruct>& b,
const double c,
std::vector<std::pair>& d,
mxArray **e
);
extern "C" {
#endif
void myFunc(const std::vector<myStruct>& a,
const std::vector<myStruct>& b,
const double c,
std::vector<std::pair>& d,
mxArray **e
);
#ifdef __cplusplus
}
#endif
#endif
The C file to call it, myFuncCaller.c:
#include "myFunc.h"
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
myFunc(prhs[0], prhs[1], prhs[2], prhs[3], prhs[4]);
}
The actual implementation:myFunc.cpp:
#include "myFunc.h"
void myFunc(const std::vector<myStruct>& a,
const std::vector<myStruct>& b,
const double c,
std::vector<std::pair>& d,
mxArray **e
)
{
//things done here, pushes results to d
}
The end result of trying to compile both of these is that:
One large hurdle is the approach of passing input arguments from MATLAB -> C -> C++. I don't want things to be "lost" and ideally don't want to do conversion unless necessary, and I'm not sure where that would be.
Upvotes: 0
Views: 171
Reputation: 60770
You cannot put std::vector<>
in an extern "C"
section, as it's not valid C syntax. You need to create a pure C function stub, compiled as C++, that calls the C++ function.
But, you don't need to do any of that because you can compile a C++ MEX-file just fine. The API is C, but you can call C functions from C++ without problem.
The actual problem in your mexFunction
is that you pass pointers to mxArray
objects where the function expects references to std::vector<>
etc. The only way to do this right is to copy the data from the MATLAB array into a C++ vector:
#include "myFunc.h"
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nrhs < 5) {
mexErrMsgTxt("Not enough input arguments! 5 expected.");
}
// arg 1: std::vector<myStruct>
if (!mxIsDouble(prhs[0])) {
mexErrMsgTxt("First input argument must be a double array.");
}
std::size_t N = mxGetNumberOfElements(prhs[0]);
double* pr = mxGetPr(prhs[0]);
std::vector<myStruct> a(N);
std::copy(pr, pr+N, a.begin());
// arg 2: std::vector<myStruct>
std::vector<myStruct> b;
// ...
// arg 3: double
double c = mxGetScalar(prhs[2]);
// arg 4: std::vector<std::pair> // This makes no sense in C++, std::pair<> is a template, 2 template arguments missing!!
std::vector<std::pair> d;
// ...
// arg 5: mxArray ** // is this the output? Why does your C++ function take an mxArray?
myFunc(a, b, c, d, &prhs[4]);
}
Upvotes: 1