1. 程式人生 > >matlab和c++混合程式設計---方法和步驟

matlab和c++混合程式設計---方法和步驟

  摘要:Matlab具有很強的數值計算和分析等能力,C/C++是目前最為流行的高階程式設計語言,兩者互補結合的混合程式設計在科學研究和工程實踐中具有非常重要的意義。從Matlab呼叫C/C++程式碼及C/C++呼叫m檔案兩方面,深入地研究了它們之間混合程式設計的原理和實現機制,並且給出了具體條件下的混合程式設計方法和步驟。實驗表明,給出的MatlabC/C++混合程式設計介面及應用方法是有效、實用的。

1引言

Matlab是當前應用最為廣泛的數學軟體,具有強大的數值計算、資料分析處理、系統分析、圖形顯示甚至符號運算等功能[1]。利用這一完整的數學平臺,使用者可以快速實現十分複雜的功能,極大地提高工程分析計算的效率

[2][3]。但與其他高階程式[3]相比,Matlab程式是一種解釋執行程式,不用編譯等預處理,程式執行速度較慢[4]

C/C++語言是目前最為流行的高階程式設計語言之一[5]。它可對作業系統和應用程式以及硬體進行直接操作,用C/C++語言明顯優於其它解釋型高階語言,一些大型應用軟體如 Matlab 就是用C語言開發的。

  在工程實踐中,使用者經常遇到MatlabC/C++混合程式設計的問題。本文基於Matlab 6.5VC6.0開發環境,在Windows平臺下就它們之間的混合程式設計問題進行深入研究並舉例說明。

2  Matlab呼叫C/C++

Matlab呼叫C/C++的方式主要有兩種:

利用MEX技術呼叫C/C++動態連線庫

  在MatlabC/C++混合程式設計之前,必須先對Matlab的編譯應用程式mex和編譯器mbuild進行正確的設定[1]

  對Matlab編譯應用程式mex的設定:Mex –setup.

  對Matlab編譯器mbuild的設定:Mbuild –setup.

2.1呼叫C/C++MEX檔案

MEXMatlab Executable的縮寫,它是一種可在Matlab中呼叫的C(Fortran)言衍生程式”[6]MEX檔案的使用極為方便,其呼叫方式與Matlab的內建函式完全相同,只需在Matlab命令提示符下鍵入MEX檔名即可。

一個C/C++MEX源程式通常包括4個組成部分,其中前3個是必須包含的內容,第4個則根據所實現的功能靈活選用:(1)#include “mex.h”;(2)MEX檔案的入口函式mexFunction, MEX檔案匯出名必須為mexFunction函式;(3)mxArray;(4)API函式

  通過簡單的例子說明C/C++MEX源程式編寫和呼叫過程:

#include "mex.h"

void  timeSTwo(double y[], double x[])

{  y[0] = 2.0*x[0];  }

void  mexFunction(int  nlhs,  mxArray * plhs[], int nrhs,  const mxArray *prhs[])

{

double *x,*y;  int  mrows, ncols;

if( nrhs!=1)  mexErrMsgTxt("One input required.");

else if( nlhs>1) mexErrMsgTxt("Too manyoutput arguments");

mrows = mxGetM( prhs[0] );  ncols = mxGetN(prhs[0]);

if( !mxIsDouble(prhs[0]) || mxIsComplex( prhs[0] ) || !( mrows ==1 && ncols==1 ) )

mexErrMsgTxt( "Input must be a noncomplex scalar double." );

plhs[0] = mxCreateDoubleMatrix (  mrows,  ncols,  mxREAL );

x = mxGetPr( prhs[0] );   y = mxGetPr( plhs[0] );timestwo(y,x);}

 可在matlab中編譯,也可以直接在C++環境中編譯: 

1.matlab)用指令mex  timestwo.c編譯此檔案,然後在MATLAB命令列下呼叫生成的MEX檔案即可。2). VC2008和一般c++一樣編譯後,就會產生dll,這樣可以直接在Matlab中用了,或者copy且更改字尾名.mexw32即可。(因為Matlab R2010b以後版本可能不支援呼叫dll為字尾的mex檔案了

2.2呼叫C/C++動態連線庫(即:一般普通的C程式dll沒有用mex的介面函式)

Matlab提供對動態連線庫DLL檔案的介面[7]。利用該介面,可在Matlab中呼叫動態連線庫匯出的函式。MatlabDLL的介面支援各種語言編寫的DLL檔案。在呼叫DLL檔案之前,需要準備函式定義的標頭檔案。對於C/C++語言開發的DLL檔案,可使用源程式中相應的標頭檔案;而對於其他語言開發的DLL,則要手工準備等效的C語言函式定義標頭檔案。

Matlab中利用動態連線庫介面技術通常需要完成以下4個步驟:

(1)開啟動態連線庫檔案;(2)為呼叫函式準備資料;(3)呼叫動態連線庫檔案中匯出的函式;(4)關閉動態連線庫檔案。

  為了實現以上步驟,用到的Matlab函式有:loadlibrary, loadlibrary, calllib, libfunctions, lipointer, libstruct, libisloaded。下面舉例說明Matlab呼叫C/C++動態連線庫的方法和步驟:

a.VC環境下,新建工程->win32動態連線庫->工程名Test1->empty工程->完成;

b.新建->C++原始檔->新增a.cpp,內容為:#include "a.h"

_declspec(dllexport)int  add(int a,  int b)  { return a+b; }

c.新建->C/C++標頭檔案->新增a.h,內容為: _declspec(dllexport)  int  add(int a,intb); 然後編譯生成Test1.dll動態連線庫檔案,將Test1.dlla.h拷到Matlab 工作目錄下。

d.Matlab命令列下,呼叫Test.dll>>loadlibrary(‘Test1’,’a.h’);>>x=7;

>>y=8;>>calllib(‘Test1’,‘add’,x,y);Ans=15  >>unloadlibrary(‘Test1’).

呼叫DLL動態連線庫的方法,為Matlab重用工程實踐中積累的大量實用C/C++程式碼提供了一種簡潔方便的方法。與呼叫MEX檔案相比,該方法更加簡便實用。但是這個介面之支援C,不支援C++庫和函式的過載,這種情況下,推薦用MEX-file,若實在要用這種方法(呼叫C/C++動態連線庫),則對於C++要做一些更改,詳見http://www.mathworks.de/help/techdoc/matlab_external/f43202.html#bq__4nu-1

3  C/C++呼叫Matlab

  在工程實踐中,C/C++呼叫Matlab的方法主要有呼叫Matlab計算引擎包含m檔案轉換的C/C++檔案,以及呼叫m檔案生成的DLL檔案

3.1利用Matlab計算引擎

Matlab的引擎庫為使用者提供了一些介面函式,利用這些介面函式,使用者在自己的程式中以計算引擎方式呼叫Matlab檔案。該方法採用客戶機/伺服器的方式,利用Matlab引擎MatlabC/C++聯絡起來。在實際應用中,C/C++程式為客戶機,Matlab作為本地伺服器

C/C++程式向Matlab計算引擎傳遞命令和資料資訊,並從Matlab計算引擎接收資料資訊[2]

Matlab提供了以下幾個C語言計算引擎訪問函式供使用者使用[8]engOpen,engClose, engGetVariable,engPutVariable,engEvalString,engOutputBuffer,engOpenSingleUse, engGetVisible,engSetVisible

  下面以C語言編寫的、呼叫Matlab引擎計算方程x3 ?2x+5=0根的源程式example2.c例,說明C/C++呼叫Matlab計算引擎程式設計的原理和步驟:

#include <windows.h>  #include <stdlib.h>

#include <stdio.h>  #include "engine.h"

int  PASCAL  WinMain (HANDLE  hInstance,  HANDLE  hPrevInstance,

LPSTR lpszCmdLine,  int nCmdShow )

{

Engine  *ep;  mxArray  *P=NULL,*r=NULL;

char buffer[301];  double poly[4] = { 1,0,-2,5 };

if ( !(ep =engOpen(NULL) ) )

fprintf( stderr,"\nCan't start MATLAB engine\n" );  return EXIT_FAILURE; }

P = mxCreateDoubleMatrix( 1, 4, mxREAL);  mxSetClassName( P, "p" );

memcpy( ( char * )  mxGetPr( P ), (char *) poly,  4*sizeof(double) );

engPutVariable( ep, P );  engOutputBuffer( ep, buffer, 300 );

engEvalString( ep, "disp(['多項式',poly2str(p,'x'),'的根']),r=roots(p)" );

MESSageBox(NULL,buffer,"example2展示MATLAB引擎的應用",MB_OK);

engClose( ep );  mxDestroyArray( P );  return EXIT_SUCCESS;

}

Matlab下執行example2.exe: mex  -f  example2.c。執行結果如圖1所示:

 

利用計算引擎呼叫Matlab的特點是:節省大量的系統資源,應用程式整體效能較好,但不能脫離Matlab的環境執行,且執行速度較慢,但在一些特別的應用[9](例如需要進行三維圖形顯示)時可考慮使用。

3.2利用mcc編譯器生成的cpp hpp檔案

Matlab自帶的C++Complier--mcc,能將m檔案轉換為C/C++程式碼。因此,它為C/C++程式呼叫m檔案提供了另一種便捷的方法。下面舉例說明相應步驟:

a.新建example3.m function y=exmaple3(n)  y=0;  for i=1:n  y=y+i;  end

  儲存後在命令視窗中輸入:mcc  -t  -L  Cpp  -h  example3.

  則在工作目錄下生成example3.cppexample3.hpp兩個檔案。

b.VC中新建一個基於對話方塊的MFC應用程式Test2,新增一個按鈕,並新增按鈕響應函式,函式內容見f步。將上面生成的兩個檔案拷貝到VC工程的Test2目錄下。

c.VC中選擇:工程->設定,選擇屬性表Link選項,下拉選單中選擇Input,在物件 / 庫模組中加入lIBMmfile.lib libmatlb.lib libmx.lib libmat.lib libmatpm.lib sgl.lib libmwsglm.lib libmwservices.lib(後三個為使用Matlab圖形庫時,需加入)注意用空格分開;而在忽略庫中加入 msvcrt.lib

d.選擇屬性表C/C++選項,下拉選單選General,在預處理程式定義中保留原來有的內容,並新增MSVC,IBMPC,MSWIND,並用逗號隔開。選擇下拉選單的Precompiled Headers 選項,在自動使用預補償頁首中新增stdafx.h,然後確定。

e.選擇:工具-> 選項,屬性頁選擇目錄include files加入: C:\MATLAB6p5p1\extern\include C:\MATLAB6p5p1\extern\include\cpp然後在 Library files裡面加入: C:\MATLAB6p5p1\bin\win32 C:\MATLAB6p5p1\extern\ lib\win32\microsoft\msvc60;注意根據使用者的Matlab安裝位置,修改相應目錄。

f.在響應函式中新增標頭檔案:#include "matlab.hpp"#include "example3.hpp"函式響應程式碼為:

int i;  mwArray n;n=10;  n=example3(n);  i=n.ExtractScalar(1);

CString str;  str.Format( "example3的返回值是:%d", I );  AfxMessageBox( str );

g.編譯,連線,執行,結果如圖2所示。

 

3.3利用mcc編譯器生成的DLL 檔案

MatlabC++ Complier不僅能夠將Matlabm檔案轉換為C/C++的原始碼,還能產生完全脫離Matlab執行環境的獨立可執行DLL程式。從而可以在C/C++程式中,通過呼叫DLL實現對 Matlab程式碼的呼叫。下面通過一個簡單的例子說明C/C++呼叫m檔案生成的DLL

a.建立m檔案example4.m function result = example4(para)

x=[1 para 3];  y=[1 3 1];  plot( x,y );  result=para*2;  end.然後在命令視窗中輸入:

mcc  -t  -W  libhg: example4  -T  link: lib  -h libmmfile.mlib  libmwsglm.mlib  example4則在工作目錄下會生成example4 .dllexample4 .libexample4 .h三個檔案。

b.VC中新建一個基於對話方塊的應用程式Test3,然後新增一個按鈕及按鈕響應函式,函式內容見d步,再將生成的3個檔案拷貝到Test2工程目錄下。

c.VC編譯環境的設定如同3.2cd步;

d.在按鈕函式檔案新增如下的標頭檔案:#include "example4 .h",函式響應程式碼為:

mxArray*para=

相關推薦

matlabc++混合程式設計---方法步驟

  摘要:Matlab具有很強的數值計算和分析等能力,而C/C++是目前最為流行的高階程式設計語言,兩者互補結合的混合程式設計在科學研究和工程實踐中具有非常重要的意義。從Matlab呼叫C/C++程式碼及C/C++呼叫m檔案兩方面,深入地研究了它們之間混合程式設計的原理和

matlabc++混合程式設計---matlabvs的環境配置問題及方法步驟(轉載)

matlab和c++混合程式設計---方法和步驟 matlab和c++混合程式設計---matlab和vs的環境配置問題 摘要:Matlab具有很強的數值計算和分析等能力,而C/C++是目前最為流行的高階程式設計語言,兩者互補結合的混合程式設計在科學研究和工程實踐中具有非常重要的意義。從Matlab呼叫C

matlabc++混合程式設計---Mex結構mexFunction引數傳遞

最近的專案需要matlab和C的混合程式設計,經過一番努力終於完成了專案要解決的問題。現在就將Mex的一些經驗總結一下,當然只是剛剛開始,以後隨著學習的深入繼續新增。首先講講寫Mex的一些常規規定,然後我們會重點關注混合程式設計中最難解決資料的問題--結構到底如何轉換

MatlabC++混合程式設計——在matlab除錯過程中可以跳入VS除錯觀察.cpp檔案中的資料

1.在matlab中為.cpp使用mex編譯生成.mexw64(64位)檔案 在matlab中封裝編譯函式: compile_gc(debug_flag) compile_gc(debug_flag=1):生成兩種檔案,(.mexw64和.mexw64.pdb) compi

HalconC#混合程式設計(一):數字識別

Halcon匯出C#程式碼 using System; using HalconDotNet; public partial class HDevelopExport { public HTuple hv_ExpDefaultWinHandle; //

Qt5.8 QMLC++混合程式設計的兩種方式(附帶原始碼)

Qt5.8  QML和C++混合程式設計的兩種方式(附帶原始碼)編譯環境:win10 專業版    Qt5.8     Qt 提供了兩種在 QML 環境中使用 C++ 物件的方式:上手敲一下,很快就能理解              點選開始,中間的圖形開始變化,上面顯示時間,

MatlabC混合程式設計Matlab呼叫C

類似Matlab的指令碼語言的最大詬病就是執行速度慢,而C的編寫難度大,但執行速度快,所以用Matlab呼叫C可以很好的互補。 用Matlab呼叫C語言如下,其中mexFunction是一個介面函式,

matlabC++混合程式設計 matlab釋出、打包DLL

本文主要講述將matlab編寫好的m函式匯出成dll,以供C++程式呼叫。使用matlab命令手動打包和matlab工具箱中deploytool的使用。寫本文的主要原因是,在專案過程中遇到一個棘手問題:專案使用了vlfeat庫,而vlfeat是c編寫的,只是提供

一個基於COM元件的MatlabC#混合程式設計例項

把matlab與其他語言混合使用是一種挺實用的技巧,在前期使用matlab進行演算法設計和計算模擬,而在需要編寫程式原型的時候把matlab演算法模組嵌入到C++或C#的程式裡,一方面省的再用C++或C#重寫程式碼,另一方面也可以直接呼叫matlab裡的一些工具

C語言動態庫建立方法,以及python混合程式設計

這篇小結是2016年暑假在新疆出差階段所寫,因為專案需要所以研究了一下。 如有錯誤,歡迎互相交流。 不同編譯器實現python呼叫C語言動態庫方法小結 Windows平臺下Visual Studio 2010編譯器建立動態庫,並呼叫 第一步:建立動態dll動態庫

MATLABVS混合程式設計,除錯C程式設定的斷點顯示“當前不會命中斷點 還沒有為該文件載入任何符號”

        我遇到的問題是matlab和c++混合程式設計,但是在matlab中進行除錯的時候需要呼叫VS2013除錯cpp程式,但是設定的斷點總是出現“當前不會命中斷點 還沒有為該文件載入任何符號”,網上的方法我都試過了,沒有用,自己試出來的方法記錄一下,可能並不適合

matlabC/C++混合程式設計--Mex (六)引數傳遞

最近的專案需要matlab和C的混合程式設計,經過一番努力終於完成了專案要解決的問題。現在就將Mex的一些經驗總結一下,當然只是剛剛開始,以後隨著學習的深入繼續新增。首先講講寫Mex的一些常規規定,然後我們會重點關注混合程式設計中最難解決資料的問題--結構到底如何轉換

C++python混合程式設計之在python類建構函式中傳參方法

一、說明:C++專案中用到python相關的知識,這兩天研究了一下C++與python的混合程式設計,網上有很多這方面的介紹,但是怎麼使用python類的建構函式中傳參的介紹卻沒有,這裡研究一下,分享出來。(C++和python相互呼叫的相關介面查詢https:

QT之C++QML混合程式設計學習筆記

QML中使用C++物件 建立一個測試用的C++物件 #ifndef PIECHART_H #define PIECHART_H #include <QtQuick/QQuickPaintedItem> #include <QColor> #include <

Python與C混合程式設計!是PythonC都不具備的超能力!

    編寫 c => python 的介面檔案 // vectory_py.c extern "C" { vector<point_t>* new_vector(){ return new vector<point_t>

c++cuda混合程式設計記錄二

/////帶有繼承關係的記憶體分配遇到了問題,父類,子類 sphere *world_device; cudaMalloc( (void**)&world_device,s

MATLABVS混合程式設計

查了很多資料,最後終於成功了,不容易記錄一下。 MATLAB R2014a,VS2013; 首先在matlab編寫一個測試函式 function [sum,prod]=sum_prod(p1,p2)     sum=p1+p2;     prod=p1.*p2; 在命令框

[C#]非同步程式設計: asyncawait(2)

一、哪裡來的執行緒? async標記的方法的方法體會被編譯到一個內部結構體的MoveNext方法中,有兩個MoveNext呼叫者是來自於主執行緒之外的同一個工作執行緒。 這一個執行緒是何時發起的呢? Task相關的操作有哪些? 1 // 三、理解await 2 bool '<&

[C#]非同步程式設計: asyncawait(1)

[C#]剖析非同步程式設計語法糖: async和await 一、難以被接受的async 自從C#5.0,語法糖大家庭又加入了兩位新成員: async和await。 然而從我知道這兩個傢伙之後的很長一段時間,我甚至都沒搞明白應該怎麼使用它們,這種全新的非同步程式設計模式對於習慣了傳統模式的人來

javagroovy混合程式設計時提示找不到符合錯誤解決辦法

本人在使用java和groovy混合程式設計時,發現一個問題,當java和groovy相互呼叫的過程中在本機執行沒有任何問題,但當弄到Jenkins上之後總是報錯,本機使用gradle執行build的task的時候,也是報錯,資訊如下: 錯誤: 找不到符號 import com.fission