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文件包含了所有庫函數 庫目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM