使用带有MEX包装器的辅助C文件从MATLAB 2016调用C ++代码时遇到问题

时间:2019-05-30 20:11:47

标签: c++ c matlab mex extern

我需要从MATLAB 2016调用C ++非成员函数。MATLAB直到2018年才支持C ++ MEX,因此这是一个问题。

我正在Windows的mingw64上执行此操作。

为了解决这个问题,我尝试使用MEX包装器制作一个C文件,C的实现纯粹是基于在线建议,使用带有外部“ C”的共享头文件调用C ++函数。

但是,我对MATLAB还是很陌生,在这里从C和其他一些概念调用C ++。因此,任何东西都无法正确编译。

对于正确解决此问题的任何建议,我们深表感谢。

头文件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

要调用它的C文件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]);
}

实际实现: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
}

尝试同时编译这两个文件的最终结果是:

  • C文件看不到mex.h(不确定为什么,因为MATLAB声称mingw是投诉)
  • 头文件可能全都错了,并声称“标准声明中类型默认为int”。我假设这是因为我在C部分中有一些与C ++相关的东西。我不确定该如何处理。
  • C ++文件抱怨最多。我可以发布所有错误,但考虑到我的逻辑中可能存在根本性缺陷,我认为这样做不会有效果。

一大障碍是从MATLAB-> C-> C ++传递输入参数的方法。我不希望事情“丢失”,理想情况下除非必要,否则不要进行转换,而且我不确定会在哪里。

1 个答案:

答案 0 :(得分:1)

  1. 您不能将std::vector<>放在extern "C"节中,因为它不是有效的C语法。您需要创建一个纯C函数存根,将其编译为C ++,然后调用C ++函数。

  2. 但是,您无需执行任何操作,因为您可以编译C ++ MEX文件。该API是C,但是您可以毫无问题地从C ++调用C函数。

  3. 您的mexFunction中的实际问题是,您传递了指向mxArray对象的指针,这些对象在函数中希望引用std::vector<>等。唯一的方法是将数据从MATLAB数组复制到C ++向量中:

#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]);
}