潘大夫,汪渤,周志强:Matlab 与 C/C++混合编程技术研究
计算机工程与设计 Computer Engineering and Design
2009,30 (2)
465
计算机应用
Matlab 与 C/C++混合编程技术研究
潘大夫, 汪 渤, 周志强
(北京理工大学 信息科学技术学院自动控制系,北京 100081)
摘 要:Matlab 具有强 大的数值计算 和分析等能力,而 C/C++是 目前最为流行的 高级程序设计 语言,两者 互补结合的混 合编
程在 科学研究和工程 实践中具有非 常重要的意义。因此,从 Matlab 调用 C/C++代码及 C/C++ 调用 m 文件 两方面,深入地 研究
了它 们之间混合编程 的原理和实现 机制,并且给出了具 体条件下的混合 编程方法和步 骤。实例表明,提出 的 Matlab 与 C/C+
+ 混合编程方法是 简洁、有效的。
关键 词:Matlab; C/C++; 混合 编程; 计算引 擎; MEX; DLL
中图 法分类号:TP391
文章编号:1000-7024 (2009) 02-0465-04
文献标 识码:A
Research on mixed programming technology of Matlab and C/C++
(Department of Automatic Control, School of Information Science and Technology, Beijing Institute of Technology,
PAN Da-fu, WANG Bo, ZHOU Zhi-qiang
Beijng 100081, China)
Abstract:Matlab has strong ability of numerical value calculation and analysis, whereas C/C++ is one of the most popular programming
languages. And the mixed programming of Matlab and C/C++ is significant in scientific research and engineering applications. Therefore,
the mechanism of Matlab inducing C/C++ codes and C/C++ calling m file are proposed separately. The mixed programming methods
and approaches in different conditions are also presented. At last,
the validity of the mixed programming between Matlab and C/C++ is
testified with some examples.
Key words:Matlab; C/C++; mixed programming; compution engineer; MEX; DLL1
0 引 言
1 配置 Matlab 编译环境
Matlab 是当前应用最为广泛的数学软件,具有非常强大
的数值计算、数据分析处理、系统分析、图形显示甚至符号运
算等功能 [1]。它为用户提供了一种比其它工具更为简洁、自
由、可移值性好的编程环境。利用这一完整的数学平台,用户
可以快速实现十分复杂的功能,极大地提高工程分析计算的
效率[2-3]。但与其它高级程序[4]相比,Matlab 程序是一种解释执
行程序,不用编译等预处理,因此Matlab 程序运行速度较慢[1]。
C/C++语言是目前最为流行的高级程序设计语言之一[4-5]。
它可对操作系统和应用程序以及硬件进行直接操作,C/C++语
言明显优于其它解释型高级语言,一些大型应用软件如Matlab
就是用 C 语言开发的。在工程实践中,用户有时需要在 Matlab
环境中调用已编写的 C/C++代码,有时需要在 C/C++中调用
Matlab 编写的数值处理、矩阵运算等代码,这就产生了 Matlab
和 C/C++混合编程的问题。因此,本文基于常用的 Matlab6.5
和 VC6.0 开发环境,在 Windows 平台下就它们之间的混合编
程问题从 Matlab 调用 C/C++和 C/C++调用 Matlab 两方面进行
深入研究并举例说明。
在 Matlab 与 C/C++混合编程之前,必须先对 Matlab 的编
译应用程序 mex 和编译器 mbuild 进行正确的设置[1]:
对 Matlab 编译应用程序 mex 的设置:
Mex -setup
然后按系统提示进行选择。
对 Matlab 编译器 mbuild 的设置:
Mbuild -setup
同样,按后面提示选择即可。
2 Matlab 调用 C/C++
Matlab 调用 C/C++的方式主要有两种:利用 MEX 技术和
调用 C/C++动态连接库。
2.1 调 用 C/C++ 的 MEX 文 件
MEX 是 Matlab Executable 的缩写,它是一种“可在 Matlab
中调用的 C(或 Fortran)语言衍生程序”[6]。即 MEX 文件的源码
是由 C 或 Fortran 语言编写的;后经 Matlab 编译器处理而生成
的二进制文件;它是可以被 Matlab 解释器自动装载并执行的
E-mail:pandaful@bit.edu.cn
收稿日期:2008-01-13
基金项目:国家部委预研基金项目 (51405030104BQ0171)。
作者简介:潘大夫 (1980-),男,陕西汉中人,博士研究生,研究方向为目标识别与跟踪; 汪渤,博士,教授,研究方向为精确制导技术;周
志强,博士研究生,研究方向为地面目标识别与跟踪。
466
2009,30 (2)
计算机工程与设计 Computer Engineering and Design
动态连接程序。MEX 文件的使用极为方便,其调用方式与
Matlab 的内建函数完全相同,只需在 Matlab 命令提示符下键
入 MEX 文件名即可。因此,对于大量现有的 C/C++代码可无
须改写成 Matlab 专用的 m 文件而在 Matlab 中执行;对于那些
Matlab 运算速度过慢的算法,可以调用 C 语言编写的相应代
码,从而提高效率。
要实现 C/C++文件到 MEX 文件转换,必须在 Matlab 编译
应用程序 mex 的设置中选择 VC 编译器。一个 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];
}
/*下面这个 mexFunction 的目的是使 Matlab 知道如何调
用这个 timestwo 函数*/
}
用指令 mex timestwo.c 编译此文件,然后在 Matlab 命令行
下调用生成的 MEX 文件:
>>x = 2;
>>y = timestwo(x)
>>y =
4
现在常用的 C 语言编译器也能够编译 C++程序,使用这
些编译器,通过 mex 命令就可实现 C++语言的 MEX 文件。和
C 语言 MEX 一样,C++语言 MEX 文件也必须实现和导出 MEX
文件入口函数。在这两种语言的 MEX 文件中,mexFunction 的
定义是完全一样的,只是在 C++函数体内可以使用或调用其
它 C++语言函数。
在 Matlab 上运行 MEX 不需要任何工具箱。使用 MEX 文
件的优点是代码重用、速度提升经及功能扩展。
2.2 调 用 C/C++ 动 态 连接 库
从 Matlab6.5(R13)起,Matlab 提供了对动态连接库 DLL 文
件的接口[7]。利用这个接口,可以在 Matlab 中调用动态连接库
所导出的函数。Matlab 对 DLL 的接口支持以各种编程语言编
写的 DLL 文件。在调用 DLL 文件中的功能之前,需要准备包
含函数定义的 C 语言头文件。对于 C/C++语言开发的 DLL 文
件,可使用源程序中相应的头文件;而对于用其它语言开发的
DLL,则需要手工准备等效的 C 语言函数定义头文件。
在Matlab 中利用动态连接库接口技术通常需要完成以下
void mexFunction (int nlhs, mxArray *plhs [],int nrhs, const
4 个步骤:
mxArray *prhs[])
/* nlhs 是 Matlab 命令行方式下输出参数的个数;plhs[]是
输出参数;nrhs 是输入参数的个数;prhs[]是的输入参数;*/
{
double *x,*y;
int mrows,ncols;
if(nrhs!= 1)
{
mexErrMsgTxt("One input required.");
}
else if(nlhs>1)
{
mexErrMsgTxt("Too many output 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);
(1)打开动态连接库文件;
(2)为调用函数准备数据;
(3)调用动态连接库文件中导出的函数;
(4)关闭动态连接库文件。
为了完成以上步骤,常用到的 Matlab 函数有:loadlibrary,
loadlibrary,calllib,libfunctions,lipointer,libstruct,libisloaded。
下面通过例子说明 Matlab 调用 C/C++
动态连接库的方法和步骤:
(1)在 VC 环境下,新建工程->win32 动态连接库->工程名
Test1->empty 工程->完成。
(2)新建->C++源文件->添加 a.cpp,内容如下:
#include "a.h"
_declspec(dllexport) int add(int a, int b)
{
return a+b;
}
(3)新建->C/C++头文件->添加 a.h,内容如下:
_declspec(dllexport) int add(int a,int b);
然后编译生成 Test1.dll 动态连接库文件,将 Test1.dll 和 a.h
拷贝到 Matlab 工作目录下。
(4)在 Matlab 命令行下,调用 Test.dll:
>>loadlibrary(‘Test1’,’a.h’);
>>x = 7;
>>y = 8;
>>calllib(‘Test1’,‘add’,x,y)
潘大夫,汪渤,周志强:Matlab 与 C/C++混合编程技术研究
2009,30 (2)
467
Ans =
15
>>unloadlibrary(‘Test1’)
调用 DLL 动态连接库的方法,为 Matlab 重用科研实践中
积累的大量实用 C/C++代码提供了一种简洁方便的方法。与
调用 MEX 文件相比,该方法更加简便实用。
3 C/C++调用 Matlab
在工程实践中,C/C++调用Matlab 的方法主要有调用 Mat-
lab 计算引擎、包含 m 文件转换的 C/C++文件,以及调用 m 文
件生成的 DLL 文件。
3.1 利 用 Matlab 计 算 引 擎
Matlab 的引擎库为用户提供了一些接口函数[7-8],利用这些
接口函数,用户可在自己的程序中以计算引擎方式调用 Matlab
文件。该方法采用客户机/服务器的计算方式,利用 Matlab 引
擎将 Matlab 和 C/C++联系起来。在实际应用中,C/C++程序为
客户机,Matlab 作为本地服务器。C/C++程序向 Matlab 计算引
擎传递命令和数据信息,并从 Matlab 计算引擎接收数据信息。
Matlab 提供了以下几个 C 语言计算引擎访问函数供用户
使用 [2,8]:engOpen,engClose,engGetVariable,engPutVariable,eng-
EvalString,engOutputBuffer,engOpenSingleUse,engGetVisible,
engSetVisible。
下面以 C 语言编写的调用 Matlab 引擎计算方程 3 2 +
5 = 0根的源程序 example2.c 为例,说明 C/C++调用 Matlab 计算
引擎编程的原理和步骤:
#include
#include
#include
#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
exmaple2.exe 的运行结果如图 1 所示。
图 1
exmaple2.exe 运行结果
以上是用 Matlab 自带的编译应用程序 mex 对 Example2.c
编译的。C/C++源程序也可在当前流行的 VC 开发环境下编
译:将 libeng.lib 和 libmx.lib 两个静态链接库加入当前工程,选
择 Project 菜单的 Settings 项,在“link/object/library modules”中
填入两个静态链接库的完整目录即可。
利用计算引擎调用 Matlab 的特点是:节省大量的系统资
源,应用程序整体性能较好,但不能脱离 Matlab 的环境运行,
且运行速度较慢,但在一些特别的应用(例如需要进行三维图
形显示)时可考虑使用。
3.2 利 用 mcc 编 译 器 生 成的 cpp 和 hpp 文件
从 Matlab 的 5.1 版本开始,Matlab 提供了自带的 C++Com-
plier--mcc,该编译器能够将 Matlab 的 m 文件转换为 C/C++代
码[1]。因此,它为 C/C++程序调用 m 文件提供了另一种便捷的
方法。下面举例说明相应步骤:
(1)建 m 文件 example3.m,内容为:
function y = exmaple3(n)
y = 0;
for i = 1:n
y = y+i;
end
保存后在命令窗口中输入:
(格式:mcc-t-L Cpp-h 文件名)
mcc-t-L Cpp-h example3
然后会在工作目录下生成 example3.cpp 和 example3.hpp
两个文件。
(2)在 VC 中新建一个基于对话框的 MFC 应用程序 Test2,
添加 Test 按钮及响应函数,函数内容见 e 步。将上面生成的
两个文件拷贝到 Test2 工程目录下。
(3) 在 VC 中选择:工程->设置,选择属性表 Link 选项,下
拉菜单中选择 Input,在对象/库模块中加入 libmmfile.lib libma-
tlb.lib libmx.lib libmat.lib libmatpm.lib sgl.lib libmwsglm.lib lib-
mwservices.lib,注意用空格将它们格开;而在忽略库中加入
msvcrt.lib;然后选择属性表 C/C++选项,下拉菜单选 General,
在 预 处 理 程 序 定 义 中 保 留 原 来 有 的 内 容, 并 添 加 MSVC,
IBMPC,MSWIND,并用逗号将它们隔开。再选择下拉菜单的
Precompiled Headers 选项,在“自动使用预补偿页眉”中添加
stdafx.h,然后确定。
(4)选择:工具->选项,属性页选择“目录”,在 include files
468
2009,30 (2)
计算机工程与设计 Computer Engineering and Design
里面加入:
mcc-t-W libhg: example4-T link: lib-h libmmfile.mlib lib-
C:\MATLAB6p5p1\extern\include,
C:\MATLAB6p5p1\extern\include\cpp;
然后在 Library files 里面加入:
C:\MATLAB6p5p1\bin\win32,
C:\MATLAB6p5p1\extern\lib\win32\microsoft\msvc60;注意
根据用户的 Matlab 安装位置,修改相应目录。
mwsglm.mlib example4
然 后 在 工 作 目 录 下 会 生 成 example4.dll,example4.lib,
example4.h 共 3 个文件。
(2) 在 VC 中新建一基于对话框的应用程序 Test3,然后添
加 Test 按钮及响应函数,函数内容见 d 步,再将生成的 3 个文
件拷贝到 Test3 工程目录下。
(5)在 Test 按钮响应函数所在文件中添加如下的头文件:
......
#include "matlab.hpp"
#include "example3.hpp"
......
Test 函数响应代码为:
int i;
mwArray n;
n = 10;
n = example3(n);
i = n.ExtractScalar(1);
CString str;
str.Format("example3 的返回值是:%d",i);
AfxMessageBox(str);
(6)编译,连接,执行,结果如图 2 所示。
(3)VC 编译环境的设置如同(3)、(4)步;
(4)在 Test 按钮响应函数所在文件中添加如下的头文件:
......
#include "example4.h"
.....
Test 函数响应代码为:
mxArray* para = mxCreateDoubleScalar(2);
mxArray* result;
example4Initialize();
result = mlfExample4(para);
CString str;
str.Format("%f",mxGetScalar(result));
AfxMessageBox(str);
(5)编译,连接,执行,结果如图 3 所示。
图 2 Test2 运行结果
注意:如果用户程序中用到其它函数,Matlab 将为每个函
数生成对应的 hpp 和 cpp 文件,必须将它们拷贝到工程目录下。
此方法虽能将 m 文件转化为 C/C++代码,然后包含到 C/
C++程序中。但是每次都需要把 Matlab 生成的一大堆 cpp 和
hpp 文件拷到 C/C++工程中,这是很不方便的。
3.3 利 用 mcc 编 译 器 生 成的 的 DLL 文 件
Matlab 自带的 C++ Complier 不仅能够将 Matlab 的 m 文件
转换为 C/C++的源代码,还能产生完全脱离 Matlab 运行环境
的独立可执行 DLL 程序。从而可以在 C/C++程序中,通过调
用 DLL 实现对 Matlab 代码的调用。下面,通过一个简单的例
子说明 C/C++调用 m 文件生成的 DLL:
(1)建立 m 文件 example4.m:
function result = example4(para)
x = [1 para 3];
y = [1 3 1];
plot(x,y);
result = para*2;
然后在命令窗口中输入:
(格式:mcc-t-W libhg:<生成的 dll 文件名>
-T link:lib-h libmmfile.mlib libmwsglm.mlib 文件名)
图 3 Test3 运行结果
利用 mcc 编译器生成的 DLL 动态连接库文件,只需在 C/
C++编译环境中将其包含进来,调用导出函数即可实现原 m
文件的功能,极大地方便了用户的代码设计。
4 结束语
本文从 Matlab 调用 C/C++代码和 C/C+调用 m 文件两方
面,详细研究了 Matlab 与 C/C++混合编程技术。对于 Matlab
调用 C/C++代码,给出了常用的 MEX 技术和调用 C/C++动态
连接库的方法,并对它们进行比较。针对实际中经常遇到的
C/C++调用 Matlab 问题,通过研究给出了常用的 3 种方法及其
特点:利用 Matlab 计算引擎的方法,由于混合编程后的可执行
程序脱离不了 Matlab 的运行环境,运行速度很慢;利用 mcc 编
译器将 m 文件转化为 C/C++文件的方法,虽能独立于 Matlab 运
行环境,但在C/C++环境中包含生成的文件非常繁琐;然而,调
用 m 文件生成的 DLL 为用户提供了一种简洁有效的方法。除
了 Matlab 自带的 mcc 外,Matcom 也能将 m 文件编译为 C/C++
文件和 DLL 文件[2,6],但混合编程原理一样,在此省略。
(下转封三)
徐红艳,冯勇:基于 Agent 集成学习情境的 E_Learning 系统设计与实现
2009,30 (2)
521
信息,知识资源 Agent 承担了知识抽取工作,服务器支出较少。
并且个人需求的处理也已在系统构建时完成,这极大地减少
了在线处理量;最终使用 CAIS 学习的学生在学习效率 (人均
完成课程所需上机时间)和学习效果(考试通过率)方面都得到
了显著的提升。对比的结果反映出依据本文所给设计实现的
基于 Agent 集成学习情境的 E_Learning 系统具有良好的系统
性能,有利于提高用户的学习效率。
表 4 传统 E_Learning 系统与 CAIS 应用效果的对比
指标
传统 E_Learning 系统 CAIS
初始用户界面生成速度/秒
用户界面更新速度/秒
平均服务器资源占用率/%
平均服务器输出流量/(兆字节/次)
人均完成课程所需上机时间/学时
考试通过率/%
2.378
0.756
78.6
786
35.6
77.8
1.575
0.324
35.7
58
32.7
94.4
5 结束语
当今时代,需要 E_Learning 系统适应人和知识资源分布
广泛的特征,并注重对用户个性化需求的满足。本文在分析
新需求的基础上,对 E_Learning 系统进行设计,提出了基于
Agent 集成学习情境的 E_Learning 系统框架,给出了系统关键
组件的实现方法,最后对系统加以实现,并分析了系统的应用
效果。通过应用效果的对比可知,基于 Agent 集成学习情境的
E_Learning 系统具有良好的系统性能,并能有效提高用户的学
习效率。为更好满足用户个性化学习需求,下一步研究的重
境[J].计算机时代,2005(3):3-4.
[5] 何烽,魏顺平,韩光艳.E_Learning 在企业的实施与应用[J].经济
师,2004(12):103-104.
[6] Duke H C,Jeoungkun K,Soung H K.ERP training with a web-
based electronic learning system:The flow theory perspective[J].
International Journal of Human-Computer Studies,2007,65(3):
223-243.
[7] 杨威,苑戎.一种基于 Agent 的电子学习体系模型的研究[J].计
算机工程与应用,2004,40(11):156-158.
[8] Guidon J, Pierre S. A client-server architecture for an instruc-
tional environment based on computer networks and the internet
[J].Telematics and Informatics,1996,13(1):11-22.
[9] 周必水,谢红标.基于 Web 的智能化学习系统的设计与实现[J].
计算机工程与设计,2005,26(11):3130-3132.
[10] Wooldridge M,Jennings N R.Intelligent agents theory and prac-
tice[J].Knowledge Engineering Review,1995,10(2):115-152.
[11] Hannoun M,Sichman J S,Boissier O,et al.Dependence relation
between roles in a multi-agent system:Towards the detection of
inconsistencies in organization[C].Proc of 1st Int Workshop on
Multi-Agent Systems and Agent-based Simulation.Berlin,Ger-
many:Springer-Verlag,1998:169-182.
[12] Chen C M,Hsieh Y L,Hsu S H.Mining learner profile utilizing
association rule for web-based learning diagnosis[J].Expert Sys-
tems with Applications,2007,33(1):6-22.
[13] 周明建,高济.知识管理系统中的用户界面[J].计算机辅助设计
点是扩充用户轮廓记录的学习情境信息,使用数据挖掘算法
与图形学学报,2005,17(5):1101-1106.
发掘用户更多的认知特性,提高 E_Learning 系统的个性化服
务水平。同时结合实际需求不断完善 E_Learning 系统结构,
拓宽 E_Learning 系统的应用领域。
参考文献:
[1] 彼得·德鲁克. 巨变时代的管理 [M]. 北京: 机械工业出版社,
2006.
[14] Danilowicz C,Nguyen H C.Using user profiles in intelligent in-
formation retrieval[C].Proc of the 13th International Symposium
on Methodologies for Intelligent Systems. Berlin, Germany:
Springer-Verlag,2002:223-231.
[15] Probst G,Raub S, Romhardt K.Managing knowledge: Building
blocks for success [M]. Chichester, UK: John Wiley and Sons,
2000.
[2] 陶峻.知识密集型服务企业的演变趋势[J].生产力研究,2005(3):
[16] 周明建,陶俊才.知识管理系统中的知识推送[J].计算机辅助设
15-16.
[3] 林东清.知识管理理论与实务[M].北京:电子工业出版社,2005.
[4] 胡维华,朱杰杰,王国荣.基于网络教学的智能虚拟电子学习环
计与图形学学报,2006,18(8):1218-1223.
[17] 周明建.基于本体的开放式知识管理研究[D].浙江:浙江大学,
2004.
(上接第 468 页)
参考文献:
[1] 张志涌.精通 Matlab6.5 版[M].北京:北京航空航天大学出版社,
[4] 钱能.C++程序设计教程[M].北京:清华大学出版社,2005.
[5] 哈特.Win32 系统编程[M].2 版.北京:中国电力出版社,2003.
[6] 董长虹. Matlab 接口技术与应用 [M]. 北京: 国防工业出版社,
2003.
2004.
[2] 杨波,亓波.精通 Matlab7.0 混合编程 [M].北京:电子工业出版
[7] 张威.Matlab 外部接口编程[M].西安:西安电子科技大学出版
社,2006.
社,2004.
[3] 董维国.深入浅出 Matlab7.X 混合编程 [M].北京:机械工业出
[8] 苏金明,黄国明,刘波.Matlab 与外部程序接口[M].北京:电子工
版社,2006.
业出版社,2004.