Matlab与C++混合编程 1--在C++中调用自己写的matlab函数

在Visual Studio中使用C++中调用MATLAB程序

在matlab中可以通过mbuild工具将.m文件编译成dll文件供外部的C++程序调用,这样就可以实现matlab和C++混合编程的目的。

预先提示:这样编出的程序仍要调用Matlab底层DLL库,摆脱不了DLL底层库的支持,如果移植到无matlab环境的机器,需要安装MCR进行运行环境的支持。

本文档记录了Matlab 2019b,windows 10 x64, Visual studio 2015(解决方案平台为x64)的环境下的配置情况。
经过测试,本文档的方法对R2016a Runtime环境不可用,会报错.

准备matlab程序

编好matlab程序,例如,顶层应为如下格式:

function [c] = myAdd(a,b)
c=a+b;
return;
end

使用matlab生成dll(Dynamic Linked Library)文件

  1. 需要带有mcc编译器的matlab软件,这个可以通过在matlab命令行中输入:!mcc命令来查看: 仔细阅读打印信息之后,可以看到mcc编译器的命令使用方法。然后输入mex -setup设置语言为C++
  2. 然后在命令窗口输入mbuild -setup选中要使用的 C++ 编译器,而不是 C 编译器,在这里请选择你需要的C++编译器,尽量与C++程序开发使用的编译器保持一致。比如可以使用Visual Studio自带的Microsoft Visual C++ 2015 Professional编译器,或者其他IDE中的MINGW编译器。
  3. 选好编译器后在命令窗口输入deploytool进入编译窗口,在弹出的窗口中选择 Library Compiler ,即生成dll动态链接库的形式,之后会弹出如下窗口。
  4. MATLAB Complie对话框中的左上角APPLICATION TYPE中选择C++ Shared Library类型,在旁边的白色框中点击加号将需要编译成dll的.m文件添加到当前项目中,选择API 类型为默认的Create all interfaces,在Samples部分选择Create New Sample,然后点击myAdd.m可以看到生成了一个样例文件。然后可以点击右上角的package按钮生成dll文件了。
  5. 等待一段时间之后就可以在指定的目录下for_redistribution_files_only文件夹内看到生成dll以及相应的.h.lib文件。

mwArray API interface对应.h,.dll.lib; Matlab数据格式API对应v2文件夹下的.ctf等。
samples根据样例.m文件,例化了可用的应用程序样例文件.

在VS中调用matlab程序中的函数

  1. 使用Visual Studio新建一个win32的空的控制台项目,同时将刚刚生成的myAdd.h存放在当前项目目录下,建立lib文件夹(专门用来存放.lib文件),将myAdd.lib拷贝到该文件夹下,将myAdd.dll存放在x64/Debug目录下。然后输入C++的应用程序代码:
#include <iostream>
#include "mclmcr.h"
#include "mclcppclass.h"
#include "matrix.h"
#include "myAdd.h"

//环境变量在安装有matlab的机器上的设置为PATH: D:\Program\MATLAB\R2016a\bin\win64时可以正常运行。
//在Runtime环境下报错
//
using namespace std;

int main()
{
	if (myAddInitialize())//必须要初始化,格式为  [名字]Initialize()
	{
		cout << "初始化完成!" << endl;
	}
	else
	{
		cout << "初始化失败!" << endl;
	}
	//定义3个mwArray类型变量,用于存放矩阵
	mwArray a(2, 3, mxDOUBLE_CLASS);
	mwArray b(2, 3, mxDOUBLE_CLASS);
	mwArray c(2, 3, mxDOUBLE_CLASS);
	double x[] = { 2,3,1,5,4,5 };
	double y[] = { 8,8,7,9,11,12 };
	double *sum = new double[6];        //注意这个是指针
	// 给输入 mxArray 对象赋值
	a.SetData(x, 6);
	b.SetData(y, 6);
	//调用DLL函数
	myAdd(1, c, a, b);
	//获取结果
	c.GetData(sum, 6);
	//输出结果
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
			cout << sum[j * 2 + i] << " ";
		cout << endl;
	}
	cout << "it is successful !" << endl;
	return 0;
}
  1. 然后点击菜单栏下的项目->属性,在项目属性对话框VC++选项中,设置包含目录mylib.h的存放目录,以及matlab环境的包含目录D:\Program Files (x86)\Matlab2018a\extern\include库目录mylib.lib的存放目录及MATLAB环境的库目录,如D:\Program Files (x86)\Matlab2018a\extern\lib\win64\microsoft。链接器->输入选项中,附加依赖项:
libmat.lib
libmex.lib
mclmcr.lib
mclmcrrt.lib
mclbase.lib
myAdd.lib

并拷贝matlab的lib文件到lib目录中。
8. 依赖MATLAB环境运行:
环境变量中还要添加D:\Program Files (x86)\Matlab2018a\bin\win64等才可以正常运行。如果没有安装matlab,还需要安装MCR,并设置环境变量.

  1. 将上面生成的可执行文件.exe拷贝到你的Qt工程release/debug后生成的exe文件的同一目录下,并在Qt中运行该.exe程序即可。

补充知识:静态编译与动态编译

  1. 静态编译:编译器在把源文件(.cpp文件)编译可执行文件(.exe文件)时,主程序中调用的函数接口通过查询包含的头文件(.h),把源文件中要调用的函数代码,翻译为库文件(.lib),然后链接到可执行文件中去,使可执行文件在运行时不需要依赖于动态链接库(.dll文件)。
  2. 动态编译:编译器在把源文件(.cpp文件)编译可执行文件(.exe文件)时,主程序中调用的函数接口通过查询包含的头文件(.h),把源文件中要调用的函数代码,翻译为动态链接库文件(.dll),然后链接到可执行文件(.exe)中,在运行时,可执行文件通过查询导出库(.lib)文件,在动态链接库(.dll)中查找函数命令。所以其优点一方面是缩小了执行文件本身的体积,另一方面是加快了编译速度,节省了系统资源。缺点一是哪怕是很简单的程序,只用到了链接库中的一两条命令,也需要附带一个相对庞大的链接库;二是如果其他计算机上没有安装对应的运行库,则用动态编译的可执行文件就不能运行。
文件后缀名 文件名称 作用 文件所在目录的名称
.c,.cpp,.cc 源文件 开发者用来写程序的 源代码目录
.h 头文件 声明应用程序的函数接口 包含目录
.lib 库文件-附加依赖项 动态库中的lib包括函数在DLL中的位置信息;静态库中不止包含位置信息,还有函数代码 库目录
.dll 动态链接库文件 动态库中的DLL文件包含了所有库函数 库目录
posted @ 2019-10-23 11:34  云远·笨小孩  阅读(4552)  评论(1编辑  收藏  举报