1. 程式人生 > 其它 >Matlab 匯出c++ 庫檔案

Matlab 匯出c++ 庫檔案

技術標籤:matlab

轉載自:https://www.cnblogs.com/charleechan/p/11725356.html,感謝原作者

在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檔案包含了所有庫函式庫目錄