1. 程式人生 > >Windows下基於mingw的mex開發

Windows下基於mingw的mex開發

1. mex是什麼

mex是Matlab提供的一種混合程式設計方式。通過mex,使用者可以在Matlab中呼叫C/C++或者Fortran編寫的計算程式,加速Matlab內部的矩陣運算(尤其是加速Matlab程式碼中的for迴圈)。mex本質上是一個動態連結庫檔案,可以被Matlab動態載入並執行。

本文介紹Windows環境下基於mingw的mex開發流程和一些注意事項。

2. mex開發流程

首先執行mex -setup配置mex開發環境,主要是設定編譯器。

一般Windows下最常用的是採用Visual Studio進行開發;在Unix系統下一般是採用gcc開發。

Windows下利用mingw進行Matlab mex開發主要有兩種方式:

  1. 普通方式—使用Matlab的mex命令
    Matlab提供了mex命令,可以方便地將C/C++或者Fortran程式碼編譯為mex檔案。mex命令的選項與mingw有很多相似之處,例如-I,-L,-l等等,熟悉mingw環境的童鞋很容易上手。mex命令支援的全部選項可以輸入mex -help或者doc mex檢視。

    mex -v -g -I %MEX_INCLUDE% -L %MEX_LIBRARY% xx.c -lmx -lmex -lmat -leng -lyy -lzz

  2. 使用gnumex
    下載gnumex,參照下面方式進行安裝。
    此時輸入mex -setup就會多出一個選項,選擇gnumex即可。以後使用mex命令則預設呼叫的是mingw編譯器。
    但是這種方式有兩個侷限。首先,如其名所暗示的那樣,gnumex只能利用mingw進行mex開發,若使用mbuild將m程式碼編譯為可執行檔案或者DLL檔案,此時不能使用mingw。因為gnumex只是修改了mexopts.bat檔案。 並沒有修改mbuild相關的配置檔案。其次,需要額外安裝工具箱。比較麻煩。

上述兩種方法一般均需要在Matlab環境下操作,實際上,我們完全可以脫離Matlab環境,基於mingw編譯器完成mex檔案的開發和除錯。這主要是基於以下兩個事實:1. mex檔案本質上是一個動態連結庫檔案,可以由相應的編譯器生成。2. Matlab為Matlab與C/C++混合程式設計提供了相應的函式庫(libmx.lib, libmex.lib, libmat.lib和libeng.lib),這為我們在Matlab環境之外進行mex開發提供了可能性,因為我們連線庫中的程式碼呼叫Matlab完成相應功能。

注意:這裡所說的是mex開發可以脫離Matlab環境,而mex檔案實際執行時還需依賴Matlab執行時環境!

3. mingw mex開發例項

首先確保MATLAB_HOME已經加入環境變數:

set MATLAB_HOME=D:\Program Files\MATLAB\R2010a
path %MATLAB_HOME%/bin;%MATLAB_HOME%/bin/win32;%path%

MATLAB_HOME代表MATLAB安裝目錄,在Matlab Command下輸入matlabroot可以獲得其值。

Makefile如下:

MATLABROOT ?= "D:\Program Files\MATLAB\R2010a"

CC          = gcc
CCFLAGS     = -I${MATLABROOT}/extern/include -L${MATLABROOT}/extern/lib/win32/microsoft
MEXLIBS     = -llibmex -llibmat -llibeng -llibmx -llibut

all: yprime.mexw32

yprime.mexw32: yprime.c
    @${CC} ${CCFLAGS} -shared -fPIC -o [email protected]  $< ${CCFLAGS}

clean:
    @-rm *.mexw32.*

以下是另一個版本(呼叫Matlab mex命令,需要確保<MATLABROOT>/bin<MATLABROOT>/bin/win32已經加入系統PATH環境變數):

MATLABROOT ?= "D:\Program Files\MATLAB\R2010a"

all: yprime.mexw32

yprime.mexw32: yprime.c
    @mex -g yprime.c

clean:
    @-rm *.mexw32.*

在Windows下,脫離Matlab環境,利用mingw環境進行mex開發,並且利用Makefile進行mex專案管理,可以更加方便地控制構建流程,具有極大的靈活性。例如,如果mex需要連線第三方庫,可以這樣寫(以OpenCV為例):

MATLABROOT ?= D:\Progra~1\MATLAB\R2010a
OPENCVROOT ?= D:\Bigben\usr\opencv

OPENCVLIBS  = -lopencv_calib3d242.dll -lopencv_contrib242.dll -lopencv_core242.dll 
            -lopencv_features2d242.dll -lopencv_flann242.dll -lopencv_gpu242.dll 
            -lopencv_highgui242.dll -lopencv_imgproc242.dll -lopencv_legacy242.dll 
            -lopencv_ml242.dll -lopencv_nonfree242.dll -lopencv_objdetect242.dll 
            -lopencv_photo242.dll -lopencv_stitching242.dll -lopencv_ts242 
            -lopencv_video242.dll -lopencv_videostab242.dll
MEXLIBS     = -llibmex -llibeng -llibmat -llibmx -llibut

CC          = g++
CCFLAGS     = -I${OPENCVROOT}/include -L${OPENCVROOT}/lib -I${MATLABROOT}/extern/include 
            -L${MATLABROOT}/extern/lib/win32/microsoft 
            -Wl,--dll

.PHONY: all

all: mexCascadeClassifier.mexw32

mexCascadeClassifier.mexw32: mexCascadeClassifier.cpp
    @${CC} ${CCFLAGS} -shared -fPIC -O2 -o [email protected] $< ${OPENCVLIBS} ${MEXLIBS}
    @strip [email protected]

clean:
    @-rm *.o *.mexw32

當然,利用mex命令也能很容易實現這一點。執行mex -help,可以看到mex支援-I-L-l選項。-I用於新增標頭檔案搜尋路徑,-L新增庫檔案搜尋路徑,-l用於指定要連線的庫檔名稱。這些都與gcc/g++類似。例如,要連線OpenCV,也可以這樣寫:

mex -I${OPENCVROOT}/include -L${OPENCVROOT}/lib -I${MATLABROOT}/extern/include 
    -L${MATLABROOT}/extern/lib/win32/microsoft 
    mexCascadeClassifier.cpp ${OPENCVLIBS} ${MEXLIBS}

compile.m程式碼如下:

MATLABROOT = matlabroot;
OPENCVROOT = 'D:\Bigben\usr\opencv';

cc_include = '';
cc_include = [cc_include '-I' fullfile(MATLABROOT, '/include')];
cc_include = [cc_include '-I' fullfile(OPENCVROOT, '/include')];

cc_library = '';
cc_library = [cc_library '-L' fullfile(MATLABROOT, '/extern/lib/win32/microsoft')];
cc_library = [cc_library '-L' fullfile(OPENCVROOT, '/lib')];

mex mexCascadeClassifier.cpp ${OPENCVLIBS} ${MEXLIBS}