使用带有 MEX Wrapper 的辅助 C 文件从 MATLAB 2016 调用 C++ 代码时遇到问题
Posted
技术标签:
【中文标题】使用带有 MEX Wrapper 的辅助 C 文件从 MATLAB 2016 调用 C++ 代码时遇到问题【英文标题】:Trouble calling C++ code from MATLAB 2016 using a helper C file w/MEX Wrapper 【发布时间】:2019-05-30 20:11:47 【问题描述】:我需要从 MATLAB 2016 调用 C++ 非成员函数。MATLAB 直到 2018 年才支持 C++ MEX,所以这会产生问题。
我在 mingw64 下的 Windows 中执行此操作。
为了解决这个问题,我尝试使用 MEX 包装器制作一个 C 文件,其中 C 实现纯粹只是根据网上的一些建议使用带有 extern "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 在 std 声明中”。我假设这是因为我在 C 部分中有一些与 C++ 相关的东西。我不知道如何解决这个问题。 C++ 文件抱怨最多。我可以发布所有错误,但考虑到我的逻辑可能存在根本缺陷,我认为这不会有成效。一个很大的障碍是从 MATLAB -> C -> C++ 传递输入参数的方法。我不希望事情“丢失”,并且除非必要,否则最好不要进行转换,而且我不确定那会在哪里。
【问题讨论】:
需要注意的一点(但可能不是这里唯一缺少的)prhs[0], prhs[1], ...
的类是*mxArray
,但你的函数需要std::vector
,所以你必须这样做转换。如果您使用 C++ MEX API,输入将是 matlab::data::Array
填充在 matlab::mex::ArgumentList
内。
由于我使用的是 MATLAB 2016,遗憾的是没有 C++ MEX API,否则我会使用这些 API。正在努力解决这个问题。
【参考方案1】:
您不能将 std::vector<>
放在 extern "C"
部分中,因为它不是有效的 C 语法。您需要创建一个纯 C 函数存根,编译为 C++,调用 C++ 函数。
但是,您无需执行任何操作,因为您可以很好地编译 C++ MEX 文件。 API 是 C,但您可以毫无问题地从 C++ 调用 C 函数。
您的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]);
【讨论】:
对于上下文,它不是专门的 std::pair ,而是使用该模板的东西。我应该更清楚。它是一对无符号整数。此外, mxArray 实际上并不是输出。如果有的话,参数 4(对)将是输出,因为它是指向一个向量的指针,该向量应该由函数使用 push_back 填充。我将查看此代码和您的回复,我认为这可能是我解决问题的途径。谢谢。 @Tyler:如果你可以改变myFunc
,你可以不复制地传递MATLAB数据。您必须有一个 double*
和一个 std::size_t
输入参数,而不是每个 std::vector
。
我可以随心所欲地修改 myFunc,除了它需要什么参数。这些必须保持不变。 (它是一个更大的软件开发项目的一部分,依赖/使用未来可能会改变的特定用户定义数据类型)
我遇到了一个找不到 mex.h 的问题。我会再发一个问题,所以我可能要过几天才能回复这个原帖,让你知道我的努力是否成功。
@Tyler:您是否在 MATLAB 中使用mex
命令编译 MEX 文件?用gcc
编译比较难,很多东西都需要设置的恰到好处。如果您使用mex
命令,但找不到mex.h
,则可能需要先运行mex -setup
。以上是关于使用带有 MEX Wrapper 的辅助 C 文件从 MATLAB 2016 调用 C++ 代码时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章
使用 Matlab Coder 将 Matlab m 文件转换为 C/C++ 代码,包括 mex 文件 (mxArray)