1. VC調用Matlab DLL的方式
DLL是一個可執行的二進制文件。把很多通用的功能放在DLL中,可以供各種應用程序調用,這樣可以很好的減少外部存儲空間的佔有量,並實現代碼的共享。Matlab也支持將m程序編譯成dll,供其他語言(包括VC、VB、Fortran等)調用,下面先簡單介紹下Matlab DLL的編譯步驟:
1.1 Matlab DLL製作
(1)配置Matlab的編譯器跟,要將mex和mbuil兩個都配置成本機上安裝的VC,mbuild的配置方法同mex
(2)編譯m函數成爲dll,在matlab命令空間中使用mcc命令編譯m文件:(mcc的使用參考Matlab幫助)
示例:將一個Matlab函數MyFun 編譯成libMyFun 的命令:
mcc –W cpplib:libMyFun –T link:lib MyFun
參數說明:-W控制編譯之後的封裝格式,cpplib表示c++的lib,冒號之後是編譯輸出lib名,-T表示目標,link:lib表示連接到lib的目標,MyFun是待編譯的m文件名,編譯成功之後,會輸出三個文件:libMyFun.lib libMyFun.dll libMyFun.h
1.2 DLL在VC中調用
要想在VC集成環境下調用Matlab的DLL,實現VC和Matlab的混合編程,一般需要經過以下幾個必要的步驟:(以下以Matlab2008a和VS2005版本爲例)
(1)VC環境配置,同前面VC調用Matlab引擎方式類似,也需要配置VC的編譯環境,其中include路徑、lib路徑和前一種方式相同,加載的lib變更爲:mclmcrrt.lib、libmx.lib、libmat.lib、mclmcr.lib四個,include的頭文件變更爲:mclmcr.h、matrix.h、mclcppclass.h三個。
(2)DLL中函數的調用,先看一下m函數編譯成C++Dll之後的函數聲明,例:matlab函數:function [y, out] = CaculateFun(x, in)編譯之後對應c++的聲明:void MW_CALL_CONVCaculateFun(int nargout, mwArray& y, mwArray& out, const mwArray& x, const mwArray& in)參數int nargout指定調用時,輸出參數的個數,緊跟的後續nargout個參數y、out爲輸出參數,後續再剩下的多個參數x、in就爲輸入參數。
(3)注意事項:在VC中調用dll中的函數之前,需要先調用函數libFunInitialize初始化,在調用完函數以後,需要再調用函數libFunTerminate和mclTerminateApplication終止。
準備好了上述步驟,就可以在VC中調用DLL中函數的了,簡單的示例代碼如下:
// include matlab sys head file
#include "mclmcr.h"
#include "matrix.h"
#include "mclcppclass.h"
// include lib head file
#include "libCaculateFun.h"
// link matlab sys lib
#pragma comment(lib, "mclmcrrt.lib")
#pragma comment(lib, "libmx.lib")
#pragma comment(lib, "libmat.lib")
#pragma comment(lib, "mclmcr.lib")
// link lib
#pragma comment(lib, "libCaculateFun.lib")
void TestDeno()
{
// init lib
if (!(libCaculateFunInitialize()))
{
std::cout<<"Could not init lib !"<<endl;
return -1;
}
double xxxx[2] = {0};
double inin = 0;
double yyyy[2] = {0};
double outo = 0;
// 爲函數參數分配內存空間
mwArray mwXX(1, 2, mxDOUBLE_CLASS);
mwArray mwIn(1, 1, mxDOUBLE_CLASS);
mwArray mwYY(1, 2, mxDOUBLE_CLASS);
mwArray mwOut(1, 2, mxDOUBLE_CLASS);
// 爲輸入參數賦值
mwXX.SetData(&xxxx, 2);
mwIn.SetData(&inin, 1);
// 調用計算函數
CaculateFun(2, mwYY, mwOut, mwXX, mwIn);
// 獲取輸出參數
outo = mwOut.Get(1, 1);
// lib Terminate
libCaculateFunTerminate();
// MCR Terminate
mclTerminateApplication();
}
示例代碼通過VC調用Matlab DLL,將變量xxxx的值付給yyyy,將變量inin的值付給outo,相對簡單,就不再詳細解釋。
2. VC向Matlab函數傳遞參數
前面在介紹兩種混合編程的方式時,示例代碼中已經涉及到了參數的傳遞問題,對於VC中的簡單數據類型:變量、數組等,網上已經有很多資料介紹,前面示例代碼中也有所體現,這裏不再詳細說明。
關於複雜數據結構:用戶自定義結構體類型,處理起來比較麻煩,網上能找到的資料也較少,由於前面提及的兩種方式,在傳遞參數時,使用的數據類型是不一致的:引擎方式只能是mxArray類型,而DLL方式的參數只能是mwArray,因此需要分別介紹將結構體轉換成這兩種類型的方法:
先來定義兩個結構體:
// 三維座標系中的點
struct Postion
{
double x;
double y;
double z;
};
// 名字標示的一個座標點
struct Coordinate
{
struct Postion pos;
char name[ARRAYSIZE];
};
分別介紹將如上兩個結構體轉成Matlab能使識別的Array的方法
(1)結構體轉換成mxArray:解釋比較多餘,就直接上代碼吧
mxArray *Staruct2mxArray(struct Postion *pStaruct)
{
mxArray *pm, *mx;
mwSize m = 1, n = 1;
const int nfields = 3;
const char *fieldnames[3] = {"x","y","z"};
const mwIndex index = 0;
pm = mxCreateStructMatrix(m, n, nfields, fieldnames);
mx = mxCreateNumericMatrix(m, n, mxDOUBLE_CLASS, mxREAL);
memcpy(mxGetPr(mx), &(pStaruct->x), sizeof(double));
mxSetFieldByNumber(pm, index, 0, mx);
mx = mxCreateNumericMatrix(m, n, mxDOUBLE_CLASS, mxREAL);
memcpy(mxGetPr(mx), &(pStaruct->y), sizeof(double));
mxSetFieldByNumber(pm, index, 1, mx);
mx = mxCreateNumericMatrix(m, n, mxDOUBLE_CLASS, mxREAL);
memcpy(mxGetPr(mx), &(pStaruct->z), sizeof(double));
mxSetFieldByNumber(pm, index, 2, mx);
return pm;
}
mxArray *Staruct2mxArray(struct Coordinate *pStaruct)
{
mxArray *pm, *mx;
mwSize m = 1, n = 1;
const int nfields = 2;
const char *fieldnames[2] = {"pos","name"};
const mwIndex index = 0;
pm = mxCreateStructMatrix(m, n, nfields, fieldnames);
mx = Staruct2mxArray(&(pStaruct->pos));
mxSetFieldByNumber(pm, index, 0, mx);
n = ARRAYSIZE;
mx = mxCreateNumericMatrix(m, n, mxCHAR_CLASS, mxREAL);
memcpy(mxGetPr(mx), pStaruct->name, sizeof(char)*ARRAYSIZE);
mxSetFieldByNumber(pm, index, 1, mx);
return pm;
}
(2)結構體轉換成mwArray:
mwArray Staruct2mwArray(struct Postion *pStaruct)
{
mwSize m = 1, n = 1;
const int nfields = 3;
const char *fieldnames[3] = {"x","y","z"};
mwArray pm(m, n, nfields, fieldnames);
mwArray mx(pStaruct->x);
pm(fieldnames[0], 1, 1) = mx;
mwArray my(pStaruct->y);
pm(fieldnames[1], 1, 1) = my;
mwArray mz(pStaruct->z);
pm(fieldnames[2], 1, 1) = mz;
return pm;
}
mwArray Staruct2mwArray(struct Coordinate *pStaruct)
{
mwSize m = 1, n = 1;
const int nfields = 2;
const char *fieldnames[2] = {"pos","name"};
const mwIndex index = 0;
mxArray pm(m, n, nfields, fieldnames);
mxArray mpos = Staruct2mwArray(&(pStaruct->pos));
pm(fieldnames[0], 1, 1) = mpos;
mxArray mname(pStaruct->name);
pm(fieldnames[1], 1, 1) = mname;
return pm;
}
(3)mxArray轉換成結構體:
struct Coordinate *mwArray2Staruct(mwArray pm)
{
// 代碼僅處理 name 字段 pos 字段是三個簡單類型省略
struct Coordinate *pStaruct = new struct Coordinate;
const int nfields = 2;
const char *fieldnames[2] = {"pos","name"};
mwArray mwStr = pm.Get(fieldnames[1], 1, 1);
char *str = strdup(mwStr.ToString());
memcpy(pStaruct->name,str,sizeof(char)*ARRAYSIZE);
return pStaruct;
}
(4)mwArray轉換成結構體:
struct Coordinate *mxArray2Staruct(mxArray *pm)
{
// 代碼僅處理 name 字段 pos 字段是三個簡單類型省略
struct Coordinate *pStaruct = new struct Coordinate;
mxArray * mxname = mxGetFieldByNumber(pm, 1, 1)
mxArray * str = mxGetPr(mxname);
memcpy(pStaruct->name,str,sizeof(char)*ARRAYSIZE);
return pStaruct;
}
原文轉載自:http://www.cnblogs.com/xpvincent/archive/2013/02/05/2893046.html