VS与Matlab混合编译 - mexw64 (C++版)

版权声明:本文为博主原创文章,未经博主允许不得转载。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方法。

具体的参数及用法还是见https://ww2.mathworks.cn/help/matlab/matlab_external/cpp-mex-api.html#mw_43f0bbf9-b23e-4b59-87cf-eb770b5e6cb9

 

生成dll

   注意 要选择 x64, 点击生成->生成解决方案。

 

输出成功:

 

4.将生成的dll文件(matlab_c_plus.dll拷贝到matlab的目录下,并改后缀dll为mexw64)

调用方法: 文件名()  也就是 matlab_c_plus(1,2)

如下图调用成功~~~

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值