VS调用Matlab编译生成的DLL 编译环境设置 [吐血整理]

时间:2024-04-12 13:01:49

本贴目的: 64位编译,VS2015调用Matlab2016编译生成的DLL,搞定:各种运行错误,调试错误。

 

转载说明:

本贴内容仅仅用于软件代码的研究和学习,相关的转载和应用不得损害Microsoft和Mathworks公司的商业利益。

有条件的情况下,请稍微支持一下老美的正版软件,例如高校有经费买套正版或者买个学习版的,中国的开发者还是要参与到老外的开发体系中。如果版权所有者认定本贴已经发生侵权,请及时告知[email protected]

各位老炮:对于比较有价值的题目还是要继续发帖和回帖,帮扶新人。只看贴不回不发,论坛的魔力就没了,各位年轻时候也是泡着坛子过来的。。。

 

本贴背景:

32位编译下,VC++(Visualstudio)调用Matlab编译生成的DLL本来是一件很容易的事情,现在转到64位了,编译环境设置不当,程序无法调通。另外,参照别人的帖子copy代码,不仔细思考,容易出现各种运行报错。 

不想折腾的话,可以先用32位编译过渡一下:VS安装2010之前的版本,选用(x86) 32位编译,Matlab安装2011之前的版本,那个是支持32位编译的。这个路是通的,但是太保守,错过了新软件(个人认为VS2015的界面,好用而美腻)和新资源(OpenCV是个好东西,不安装最新的VS支持不了)。另外,OpenCV高版本只(直接)支持64位编译,所以还是要继续前进。。。 

看到很多帖子有“杂交”的想法:安装高版本VS和低版本的Matlab。VS采用64位编译,编写主程序;VS采用32位编译,编写辅助程序调用Matlab 32位DLL。主程序和辅助程序采用进程间通信,例如:COM服务器,共享内存地址,发送消息。。。这个真的是很辛苦。其中,低版本的Matlab,mbuild选择高版本VS的编译器,也是比较麻烦,这里不展开。

 

另外,VC调用Matlab C++ Math Library也是一种混合编程的解决方案,我个人不推荐。理由:有些m文件不支持C文件编译输出。功能打包和调用编程没有DLL简便。

 

本贴内容:

[1]================扫清外围问题

VS和Matlab版本兼容的问题。Matlab的编译器只支持最近的VS版本,这个用mbuild –setup测试就知道了,一般建议Matlab版本稍高。本人建议:VS2015和Matlab2016,本人电脑win7 64。

首先,Matlab本身安装必须正点,安装后无需特别设置,直接mcc 编译一个图形显示+运算的exe运行OK。所以某论坛的破2017版本不建议安装。

其次,某些同志程序调不通,就各种VS和Matlab版本安装和卸载,这个没有必要。要相信老美大公司的产品。关键是,最终也没调通。

 

[2]=========== ====实例和过程

以下步骤描述简单,但是保证完整。

M文件定义。

function c =Test(a,b)

c = a+b;

--------------------------------------

Matlab命令生成库文件和头文件

mcc -W cpplib:TestMat64 -T link:lib Test

获得所需文件,拷贝到VS工程相应目录下。

 VS2015调用Matlab编译生成的DLL 编译环境设置 [吐血整理]

电脑中添加Matlab运行环境: [ 注意:电脑重启生效!!!]

控制面板->所有控制面板项->系统->高级系统设置->高级->环境变量

Path一栏,后面追加:C:\ProgramFiles\MATLAB\R2016b\bin\win64

---------------------------------------------------------

VS编译环境设置:

添加include路径:C:\Program Files\MATLAB\R2016b\extern\include

添加lib路径:C:\Program Files\MATLAB\R2016b\extern\lib\win64\microsoft

添加附加lib:linker->input 追加

TestMat64.lib; libmx.lib; libmat.lib; mclmcr.lib;mclmcrrt.lib;   第1个是自己的M文件mcc生成的

库文件不能少,否则可以看到熟悉的编译报错:error LNK2019: 无法解析的外部符号

 

Matlab库文件的层次理解参考:

https://cn.mathworks.com/help/compiler_sdk/cxx/how-the-mclmcrrt-proxy-layer-handles-loading-of-libraries.html?searchHighlight=mclmcrrt&s_tid=doc_srchtitle&requestedDomain=true

VS2015调用Matlab编译生成的DLL 编译环境设置 [吐血整理]

 

 

VS编程调用:

学习细节可以参考官网:

https://cn.mathworks.com/help/compiler_sdk/cxx/integrate-a-cc-shared-library-into-an-application.html

https://cn.mathworks.com/help/compiler_sdk/shared-libraries.html

 

以下是VS原代码:完整

#include"TestMat64.h"// mcc DLL头文件

 mclmcrInitialize();

if (!mclInitializeApplication(NULL, 0) return;

// 上两句初始化很重要,很多同志漏掉了,直接调用自己的DLL

// 初始化可以鉴定Matlab外部调用环境设置是否正确,很多读者就是死在这里吧??后面有解答

 

if (!TestMat64Initialize())   return;

// mwArray输入变量这里是用数组间接赋值的,直接赋值报错!

mwArray a_ptr(1, 1, mxDOUBLE_CLASS, mxREAL);

mwArray b_ptr(1, 1, mxDOUBLE_CLASS, mxREAL);

double data1[] = { 1.0 };

double data2[] = { 2.0 };

a_ptr.SetData(data1, 1); //  间接赋值,不能直接赋值!!!

b_ptr.SetData(data2, 1);  

 

mwArray c_ptr;

Test(1, c_ptr, a_ptr, b_ptr);

TestMat64Terminate();

mclTerminateApplication();

double Val;    Val =c_ptr;

 

如果您到这里VS2015中按下F5一切正常,后面的就不用看了。我的电脑上不行。

 

[3] =================== 头文件包含的问题

除了Mcc生成的dll头文件TestMat64.h之外,还有几个库文件对应的头文件绕来绕去:mclmcrrt.h ,mclmcr.h ,mclcppclass.h 以及matrix.h。 

头文件少了肯定不行,VS2015的代码里面可以看到函数没有定义。

但是头文件添加多了会出现以下报错:

errorC3861: 'mclmcrInitialize_proxy': identifier not found

errorC3861: 'mclInitializeApplication_860_proxy': identifier not found

看了下面mathworks社区的一个帖子,大概搞明白了里面有一个地方容易出问题:

MATLAB Compiler 4.8 (R2008a) or laterversions 已经在mcc生成的dll头文件中包含了mclmcrrt.h 和mclcppclass.h,

如果在VS代码中再include,会导致函数重定义,无法匹配lib,典型报错如上述error C3861.

https://cn.mathworks.com/matlabcentral/answers/100242-why-do-i-receive-a-linking-error-about-mclinitializeapplication_proxy-and-mclmcrinitialize_proxy-whe

 VS2015调用Matlab编译生成的DLL 编译环境设置 [吐血整理]

该贴建议:将mcc生成的dll头文件放在最前,也就是顺序很重要。

我测试了一下,重复的头文件可以直接去掉,mclmcr.h和matrix.h也都没必要,也就是说一个头文件就搞定。

 

[4]=================调试debug错误

这个是比较挠头的问题,前面编译环境都搞定了,按下F5后,dubug output 窗口错误狂涌,一行接一行:

Exceptionthrown at 0x000007FEFCF6A06D in StartOpenCV.exe: Microsoft C++ exception:xsd_binder::MalformedDocumentError at memory location 0x00000000002887B0.

Exceptionthrown at 0x000007FEFCF6A06D in StartOpenCV.exe: Microsoft C++ exception:xsd_binder::MalformedDocumentError at memory location 0x000000000028AE30.

Exceptionthrown at 0x000007FEFCF6A06D in StartOpenCV.exe: Microsoft C++ exception:xsd_binder::MalformedDocumentError at memory location 0x00000000002887B0.

Exceptionthrown at 0x000007FEFCF6A06D in StartOpenCV.exe: Microsoft C++ exception:xsd_binder::MalformedDocumentError at memory location 0x000000000028AE30.

VS还会弹出如下对话框,提示 Frame not in module

VS2015调用Matlab编译生成的DLL 编译环境设置 [吐血整理]

 

和我一样受到困扰的人很多,最后在mathworks社区一个帖子的回复的最后面,找到了解答。

https://cn.mathworks.com/matlabcentral/answers/286624-matlab-c-shared-dll-library-initialization-problem

VS2015调用Matlab编译生成的DLL 编译环境设置 [吐血整理]

结论大概:VS自己debug有点管得太宽了。 

Visual Studio 中Propertiesof Project -> Configuration Properties -> Debugging -> Debugger Type 

原贴建议:将默认AUTO 改成 Managed Only,发现这样好像调试信息都没了,这还叫调试吗? 

本人实际测试,Mixed 效果比较好。

VS2015调用Matlab编译生成的DLL 编译环境设置 [吐血整理]

 ----完毕----