先小話一下DLL,DLL是動態連接庫,是源代碼編譯後的二進制庫文件和程序接口,和靜態連接庫不一樣的是,程序在編譯時並不連接動態連接庫的執行體,而是在文件中保留一個調用標記,在程序運行時纔將動態連接庫文件加載入內存。而且DLL在運行時是共享的,即當多個程序調用時,內存中也只保持一份動態連接庫。
動態連接庫的調用有顯式和隱式兩種方式。
隱式連接須要用到咱們前面生成的plotdata.c,plotdata.h,plotdata.lib以及plotdata.dll文件。
首先將plotdata.c,plotdata.h加入工程中,注意在須要用到函數的文件加入#include "plotdata.h".
以後連接輸入項中寫上plotdata.lib.右擊工程->Propertites->Link->Input->Additional Dependecies中加上plotdata.lib(也就是在調用MATLAB引擎時填寫libmat.lib、libeng.lib等的地方)注意plotdata.lib也須要放在你的工程下,或者寫全路徑,如"D:\data\plotadata.lib",須要加引號。
這樣在你的代碼中就能夠直接用plotdata.h中的接口函數了。
另顯式連接的方式:所謂"顯式"說白了就是在代碼中寫出來我要調用這個DLL.
首先咱們須要定義一個函數類型,方便咱們後面進行函數的強制類型轉換。咱們能夠在plotdata.h中找到咱們將要使用的函數plotdata,他的函數聲明以下:
extern LIB_plotdata_CPP_API void MW_CALL_CONV plotdata(const mwArray& rgbData);
忽略那些複雜的宏定義,模仿着定義咱們本身的函數類型:
typedef void (*HMAT)(const mwArray& rgbData);
以後在代碼中顯式連接plotdata.dll
HINSTANCE hDLL=NULL;//DLL句柄
hDLL=LoadLibrary("plotdata.dll");
HMAT plotData=(HMAT)GetProcAddress(hDLL,"plotdata");
//第一個參數爲DLL句柄,第二個爲要加載的函數名
以後即可直接在代碼中直接使用函數plotData了。這種顯式連接只須要plotdata.dll文件便可~
下面咱們來看一下生成的函數接口
extern LIB_plotdata_C_API
bool MW_CALL_CONV plotdataInitializeWithHandlers(
mclOutputHandlerFcn error_handler,
mclOutputHandlerFcn print_handler);
extern LIB_plotdata_C_API
bool MW_CALL_CONV plotdataInitialize(void);
extern LIB_plotdata_C_API
void MW_CALL_CONV plotdataTerminate(void);
extern LIB_plotdata_C_API
void MW_CALL_CONV plotdataPrintStackTrace(void);
extern LIB_plotdata_C_API
bool MW_CALL_CONV mlxPlotdata(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);
extern LIB_plotdata_C_API
long MW_CALL_CONV plotdataGetMcrID();
extern LIB_plotdata_C_API bool MW_CALL_CONV mlfPlotdata(mxArray* rgbData);
這是plotdata.h中主要的函數。plotdataInitialize(void)能夠看出是初始化的函數。若是是隱式連接DLL最好先調用此函數,判斷返回值不然極可能加載不到dll,而在顯式連接時,若是沒有加載函數成功,也不會直接報錯,但咱們能夠在單步調試時看函數是否爲分配了內存(便是否爲null)。plotdataTerminate(void)是終止動態連接庫的函數。
mlxPlotdatat與mlfPlotdata是最關鍵的兩個接口,也是咱們要加載的函數。他們執行的功能與m文件中plotdata函數是同樣的。兩個函數輸入參數不一樣:
mlxPlotdata(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]); 其中 nlhs,plhs分別表示輸出參數的個數及輸出參數的mxArray數組;nrhs,prhs表示輸入參數的個數及輸入參數數組。(這個函數有點通用的感受……)
mlfPlotdata(mxArray* rgbData); 就簡單的多,基本和m文件中你定義的plotdata函數是同樣的(個人plotdata定義爲 function []=plotdata(rgbData))
因此通常在程序中加載的是mlf開頭的函數。
這裏須要提的是我編譯生成的是C的動態連接庫。若是是生成C++的動態連接庫,生成的接口函數也帶有一個mlx開頭的函數,即
bool MW_CALL_CONV mlxPlotdata(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
可是另外一個函數是不帶有mlf的,直接爲
void MW_CALL_CONV plotdata(const mwArray& rgbData)
並且輸入參數不是mxArray數組,而是mwArray數組,這也是C和C++與MATLAB混合編程時最主要的不一樣(下篇再詳細說)
可是我在嘗試C++動態連接時一直沒有成功。後來看到生成的cpp文件同c文件同樣也有一個 extend "C"{},這是C++爲了與C兼容而提供的一個關鍵字,C++編譯器將會在extend "C"的大括號內部代碼當作C語言代碼處理,這讓我很困惑……而若是註釋掉又會報鏈接錯誤託福答案
想來多是MATLAB對C++編譯支持並很差(他自帶的lcc編譯器是隻能編譯成C的接口)總之沒有嘗試成功,暫時在程序中都用C的動態連接了。編程