版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/wwwoowww/article/details/83013801
这几天遇见一个项目,需要在matlab中调用c/c++ 代码。在matlab中直接使用mex编辑各种不方便,网上都是使用c mex在vs下编程,满足不了我的需求,幸好在在matlab官网发现提供了基于面向对象的使用方法,对比使用c mex编程的特点是:
C++ MEX functions are based on two C++ APIs:
-
The MATLAB Data API supports MATLAB data types and optimizations like copy-on-write for data arrays passed to MEX functions. For more information.
-
A subset of the MATLAB C++ Engine API supports calling MATLAB functions, execution of statements in the MATLAB workspace, and access to variables and objects. For more information.
也就是:第一次调用创建了对象,在之后的调用中,对象的状态都是持续存在的。每次的调用会使用相同的对象,能够保存一些状态~~
利用提供的API 还能在c++中调用matlab中的函数(feval(....)方法)~~~
官网介绍 c++ mex编程:https://ww2.mathworks.cn/help/matlab/matlab_external/c-mex-functions.html
c++ mex API : https://ww2.mathworks.cn/help/matlab/matlab_external/cpp-mex-api.html#mw_43f0bbf9-b23e-4b59-87cf-eb770b5e6cb9
在这里把在VS下的开发流程贴出,以便大家参考。
环境:win10,VS2017,MatlabR2018a。
1.创建项目
VS2017没有了win32选项,直接选择控制台应用程序就行。
2.添加依赖项
进入项目的属性页,在自己的项目中右键-》属性。找到 配置属性 底下的 VC++ 目录。
注意:我的是matlab提供的lib文件64位的,请在平台 x64 下编辑一下所有。
2.1我们需要在 VC++目录 设置 包含目录,库目录
(1)包含目录: 添加Matlab安装目录下的 ...\extern\include,我的是 D:\Matlab2018a\extern\include
(2) 添加 库目录: Matlab安装目录下的 ...\extern\lib\win64\microsoft ; 我的是 D:\Matlab2018a\extern\lib\win64\microsoft
2.2 添加 链接器 信息
选择 链接器-》输入-》附加依赖项—》添加一下
libmex.lib
libMatlabDataArray.lib
2.3 修改输出文件为dll 。把配置类型改为dll
点击应用,保存以上修改。
3.在文件中添加代码段(来源于matlab官网 https://ww2.mathworks.cn/help/matlab/matlab_external/c-mex-source-file.html,稍后解释)
matlab默认传入的数据类型为double,
/* MyMEXFunction
* Adds second input to each
* element of first input
* a = MyMEXFunction(a,b);
*/
#include "pch.h"
#include "mex.hpp"
#include "mexAdapter.hpp"
using namespace matlab::data;
using matlab::mex::ArgumentList;
class MexFunction : public matlab::mex::Function {
public:
void operator()(ArgumentList outputs, ArgumentList inputs) {
checkArguments(outputs, inputs);
const double offSet = inputs[0][0];
TypedArray<double> doubleArray = std::move(inputs[1]);
for (auto& elem : doubleArray) {
elem += offSet;
}
outputs[0] = doubleArray;
}
//检查输入参数格式
void checkArguments(ArgumentList outputs, ArgumentList inputs) {
// Get pointer to engine
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
// Get array factory
ArrayFactory factory;
// Check first input argument
if (inputs[0].getType() != ArrayType::DOUBLE ||
inputs[0].getType() == ArrayType::COMPLEX_DOUBLE ||
inputs[0].getNumberOfElements() != 1)
{
matlabPtr->feval(u"warning",
0,
std::vector<Array>({ factory.createScalar("First input must scalar double") }));
}
// Check second input argument
if (inputs[1].getType() != ArrayType::DOUBLE ||
inputs[1].getType() == ArrayType::COMPLEX_DOUBLE)
{
matlabPtr->feval(u"fprintf",
0,
std::vector<Array>({ factory.createScalar("Input must double array") }));
}
// Check number of outputs
if (outputs.size() > 1) {
matlabPtr->feval(u"error",
0,
std::vector<Array>({ factory.createScalar("Only one output is returned") }));
}
}
};
代码解释:
#include "mex.hpp"
#include "mexAdapter.hpp"
class MexFunction : public matlab::mex::Function {
public:
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
//TODO
// 我们的代码添加在这儿
...
}
};
类名必须是MexFunction,matlab会调用operator() 方法,我们在其中中添加自己的代码就行。如果改了名字,matlab就找不到了对象了。
outputs,inputs 分别是matlab调用中的输入和输出参数。
如何创建outputs 见: https://blog.csdn.net/wwwoowww/article/details/83111371
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
// Get array factory
ArrayFactory factory;
// Check first input argument
if (inputs[0].getType() != ArrayType::DOUBLE ||
inputs[0].getType() == ArrayType::COMPLEX_DOUBLE ||
inputs[0].getNumberOfElements() != 1)
{
matlabPtr->feval(u"error",0,std::vector<Array>({ factory.createScalar("First input must scalar double") }));
}
matlabPtr提供了多种方法,其中 matlabPtr->feval(u"error",0,std::vector<Array>({ factory.createScalar("First input must scalar double") })); 是调用了matlab中的error方法。
生成dll
注意 要选择 x64, 点击生成->生成解决方案。
输出成功:
4.将生成的dll文件(matlab_c_plus.dll拷贝到matlab的目录下,并改后缀dll为mexw64)
调用方法: 文件名() 也就是 matlab_c_plus(1,2)
如下图调用成功~~~