目 录
VC++ & Matlab 混 合 编 程 的 快 速 实 现. 2
摘 要. 2
关 键 词. 2
简 介 :. 2
实例分析. 3
1、编写Matlab函数. 3
2、Matlab6.5编译器设置. 3
3、建立C++控制台工程. 5
4、启用Matlab Add-in 工具条. 6
5、VC++6.0环境及工程设置. 7
6、Matlab到C++的代码转换. 10
7、C++函数的使用. 11
特别说明一:. 12
特别说明二:. 13
8、程序的发布. 13
总 结. 13
VC++ & Matlab 混 合 编 程 的 快 速 实 现
摘 要 :
许 多 工 程 软 件 需 要 用 到 复 杂 的 数 学 算 法 。VC++能 够 形 成 各 种 用 户 界 面 , 并 可 以 直 接 与 系 统 及 底 层 硬 件 交 换 数 据 。 因 此 研 究 VC++和 Matlab的 混 合 编 程 具 有 很 大 的 实 际 意 义 。
该 文 讨 论 了 如 何 使 用 Matlab 的 Complier 将 *.m 函 数 编 译 为 动 态 链 接 库 DLL, 提 供 VC++ 调 用 的 方 法 , 提 供 了 一 种 VC++与 Matlab 混 合 编 程 的 快 速 实 现 。
关 键 词 : Matlab VC++ MCC Complier 动 态 链 接 库 DLL
简 介 :
Matlab 作 为 当 今 世 界 上 应 用 最 为 广 泛 的 数 学 软 件 , 具 有 非 常 强 大 的 数 值 计 算 、 数 据 分 析 处 理 、 系 统 分 析 、 图 形 显 示 甚 至 符 号 运 算 的 功 能 。 已 经 在 如 生 物 工 程 , 图 像 处 理 , 语 音 处 理 , 雷 达 探 空 , 声 纳 探 水 , 地 震 探 地 , 以 及 控 制 论 , 系 统 论 等 各 个 领 域 得 到 广 泛 的 应 用 。 它 是 一 个 完 整 的 数 学 平 台 , 在 这 个 平 台 上 , 用 户 只 需 寥 寥 数 语 就 可 以 完 成 十 分 复 杂 的 功 能 , 大 大 提 高 了 工 程 分 析 计 算 、 图 像 处 理 的 效 率 。 但 是 Matlab 强 大 的 功 能 只 能 在 它 所 提 供 的 平 台 上 才 能 使 用 , 即 用 户 必 须 在 安 装 Matlab 系 统 的 机 器 上 才 能 执 行 *.m 文 件 。 这 样 当 用 户 需 要 将 在 Matlab下 已 开 发 完 毕 的 复 杂 算 法 应 用 到 高 级 语 言 开 发 环 境 下 时 就 带 了 问 题 , 是 将 现 成 的 东 西 集 成 高 级 语 言 开 发 的 程 序 中 呢 ? 还 是 用 高 级 语 言 再 重 新 实 现 一 遍 ? 显 然 大 家 所 期 望 的 是 减 少 工 作 量 , 最 好 能 将 Matlab 下 开 发 好 的 程 序 或 函 数 直 接 应 用 到 高 级 语 言 开 发 的 程 序 中 , 这 就 是 Matlab 与 高 级 语 言 的 混 合 编 程 问 题 。
VC++是 当 前 Windows 下 的 主 要 编 程 语 言 之 一 , 它 能 方 便 地 形 成 应 用 软 件 中 所 需 要 的 各 种 用 户 界 面 和 工 具 并 直 接 与 系 统 及 底 层 硬 件 交 换 数 据 。用 VC++开 发 的 系 统 具 有 容 易 维 护 升 级 、 界 面 友 好 、 代 码 效 率 高 、 执 行 速 度 快 等 一 系 列 优 点 , 因 此 已 成 为 目 前 应 用 软 件 开 发 中 广 泛 采 用 的 主 要 工 具 之 一 。 因 此 , 如 何 将 Matlab 与 VC++进 行 有 效 的 混 合 编 程 广 受 工 程 科 研 人 员 的 关 注 。 解 决 这 个 问 题 , 不 仅 能 更 好 地 发 挥 Matlab 强 大 的 功 能 , 还 能 快 速 地 进 行 软 件 开 发 , 尤 其 是 当 软 件 开 发 中 需 要 实 现 复 杂 的 数 学 算 法 、 图 形 处 理 时 尤 为 迫 切 。研 究 VC++与 Matlab 的 混 合 编 程 具 有 很 大 的 实 际 意 义 。
实例分析
1、编写Matlab函数
函数文件sum_prod.m,内容如下:
function [sum,prod] = sum_prod(p1,p2)
sum = p1+p2; % p1与p2的和
prod = p1.*p2; % p1与p2的点乘
该函数完成的是矩阵的求和与点乘的功能,下面将介绍把该代码转换成C++环境可用的代码的方法。
2、Matlab6.5编译器设置
(1) 在同一台电脑上安装Matlab6.5和Visual C++6.0;
(2) mex命令设置
(a)运行Matlab,在Matlab的命令窗口(Command Window)键入“mex -setup”命令后,按回车键,安装Matlab编译器;
(b) 命令窗口出现如下提示:
Please choose your compiler for building external interface (MEX) files:
Would you like mex to locate installed compilers [y]/n?
此时键入”y”,按回车;
(c) 命令窗口出现如下提示:
Please choose your compiler for building external interface (MEX) files:
Would you like mex to locate installed compilers [y]/n? y
Select a compiler:
[1] Digital Visual Fortran version 6.0 in C:\Program Files\Microsoft Visual Studio
[2] Lcc C version 2.4 in C:\MATLAB6P5\sys\lcc
[3] Microsoft Visual C/C++ version 6.0 in C:\Program Files\Microsoft Visual Studio
[0] None
此时键入”3”,按回车;选择Microsoft Visual C++6.0的编译器
(d) 命令窗口出现如下提示:
Please verify your choices:
Compiler: Microsoft Visual C/C++ 6.0
Location: C:\Program Files\Microsoft Visual Studio
Are these correct?([y]/n):
此时键入”y”,按回车;确认选择Microsoft Visual C++6.0的编译器
(3) mbuild命令设置
(a) 运行Matlab,在Matlab的命令窗口(Command Window)键入“mbuild -setup”命令后,按回车键,安装Matlab编译器;
(b) 命令窗口出现如下提示:
Please choose your compiler for building standalone MATLAB applications:
Would you like mbuild to locate installed compilers [y]/n?
此时键入”y”,按回车;
(c) 命令窗口出现如下提示:
[1] Lcc C version 2.4 in C:\MATLAB6P5\sys\lcc
[2] Microsoft Visual C/C++ version 6.0 in C:\Program Files\Microsoft Visual Studio
[0] None
此时键入”2”,按回车;选择Microsoft Visual C++6.0的编译器
(d) 命令窗口出现如下提示:
Please verify your choices:
Compiler: Microsoft Visual C/C++ 6.0
Location: C:\Program Files\Microsoft Visual Studio
Are these correct?([y]/n):
此时键入”y”,按回车;确认选择Microsoft Visual C++6.0的编译器
(4) 在Matlab的命令窗口(Command Window)键入“cd(prefdir); mccsavepath prefdir;”启动MATLAB add-in工具条
3、建立C++控制台工程
(1) 新建一个C++控制台工程Test
其它都采用默认设置。然后在该工程中添加Test.cpp文件
4、启用Matlab Add-in 工具条
(1) 在上面的VC工程中,在菜单栏的空白处右键单击鼠标,出现如下菜单
点击Coustomize…菜单项,出现如下Coustomize对话框,
选择Add-in and Macro Files标签,选中MATLAB Add-in选项,点Close按钮关闭对话框,这里会在菜单附近出现如下工具条,它就是Matlab Add-in 工具条。
5、VC++6.0环境及工程设置
在上面的VC工程中,进行以下设置
(1) VC++6.0环境设置
单击菜单Tools,出现如下菜单
单击Options…菜单项,出现Options对话框,选择Directories标签,在include files里面加入:
C:\MATLAB6P5\EXTERN\INCLUDE
C:\MATLAB6P5\EXTERN\INCLUDE\CPP
如下图所示
在Library files里面加入:
C:\MATLAB6P5\EXTERN\LIB
C:\MATLAB6P5\EXTERN\LIB\WIN32
C:\MATLAB6P5\EXTERN\LIB\WIN32\MICROSOFT\MSVC60
如下图所示
(2) VC++6.0工程设置
单击菜单Project,出现如下菜单
单击Setting…菜单项,出现Project Setting对话框,选择Link标签,在 Object/library modules: 下面的文本框内容的后面加入libmmfile.lib libmatlb.lib libmx.lib libmat.lib libmatpm.lib sgl.lib libmwsglm.lib libmwservices.lib,如下图所示
选择C/C++标签,在 Prerocessor definitions: 下面的文本框内容的后面加入 ,MSVC,IBMPC,MSWIND,如下图所示
设置完成。
6、Matlab到C++的代码转换
在上面的VC工程中
(1) 将前面sum_prod.m文件复制到该Test工程所在的目录下
(2) 单击Matlab Add-in 工具条最左边第一个按钮,出现如下对话框
选中Windows Console EXE 四个选择选中后二项,如上图所示,单击OK,出现如下对话框
选中Matlab函数文件sum_prod.m,单击“打开”按钮,这样在该工程所在的目录就生成了sum_prod.cpp和sum_prod.hpp文件。
(3) 打开sum_prod.cpp文件,注意到里面有这样一个函数
mwArray sum_prod(mwArray * prod, mwArray p1, mwArray p2)
{…}
可以看到在C++环境中,sum_prod也是一个函数,它的输入与输出数据类型是mwArray,它是VC6.0专门为Matlab中的矩阵对象定义的一个类。函数sum_prod有三个输入参数和一个输出参数。由于C++函数不能有一个以上的返回值,因此这里将Matlab函数sum_prod的第二个返回值,以地址型变量的形式作为C++函数sum_prod的第一个输入参数。
7、C++函数的使用
在上面VC工程Test.cpp文件中键入以下代码:
//********************************************************************
#include "matlab.hpp" // 包含类mwArray定义
#include "sum_prod.hpp" // 包含C++函数sum_prod
void main()
{
int i,j;
// 定义C++二维数组
double x[] = {1,2,3,4,5,6};
double y[] = {7,8,9,10,11,12};
double *sum,*prod;
// 初始化与C++数组相对应的mwArray变量
mwArray X(2,3,x);
mwArray Y(2,3,y);
mwArray SUM,PROD;
// 调用C++函数
SUM = sum_prod(&PROD,X,Y);
// 给输出数据分配内存
sum =(double*) calloc(6,sizeof(double));
prod =(double*) calloc(6,sizeof(double));
// 取出输出数据
sum = mxGetPr(SUM.GetData());
prod = mxGetPr(PROD.GetData());
// 输出显示
cout << "SUM = " << endl;
for (i=0;i<2;i++)
{
for (j=0;j<3;j++)
cout << sum[j*2+i] << "\t";
cout << endl;
}
cout << "PROD = " << endl;
for (i=0;i<2;i++)
{
for (j=0;j<3;j++)
cout << prod[j*2+i] << "\t";
cout << endl;
}
// 释放内存
free(sum);
free(prod);
}
//********************************************************************
编译链接程序,“忽略”编译过程中有关库文件msvcrt.lib的警告。
该C++程序运算结果如下图所示
特别说明一:
在C\C++环境中二维数组是“行向量”,如果将下面定义的变量x看成二维数组的话
double x[] = {1,2,3,4,5,6};
那么x应该是的矩阵,即
x = [1,2,3;
4,5,6];
但是,如果将数组首地址x初始化mwArray类时,数组x在mwArray中是按“列向量”的形式排列的,即
X = [1,3,5;
2,4,6];
同理,这里
Y = [7,9,11;
8,10,12];
因此才能得到上图的结果
特别说明二:
通过Matlab Add-in实现Matlab与VC++的混合编程也有不足,并不是所有的Matlab的函数都能转成C++函数,这一点在使用过程中要特别注意!
8、程序的发布
(1) 使用 VC 附带的 Depends 工具找到应用程序所需要的 dll 文件,手动复制这些文件添加到应用程序所在的目录即可。
(2) 编译好的程序只要附带 mglarchive.exe (在 C:\MATLAB6p5\extern\lib\win32 目录) 中的数学和图形库即可在没装 matlab 的机器上运行
总 结
从 以 上 的 讨 论 中 可 以 清 楚 的 看 到 , 使 用 Matlab 生 成 动 态 链 接 库 (*.DLL) 实 现 VC++ 和 Matlab 的 混 编 的 确 以 它 的 方 便 , 易 用 成 为 VC++和 Matlab 混 编 的 一 种 快 速 实 现 方 法 。 另 外 ,Matlab 的 Compiler 也 具 有 一 定 的 局 限 性 : 原 则 上 在 混 编 的 过 程 中 只 能 使 用 Matlab 数 学 库 中 的 函 数 和 图 形 库 中 的 部 分 函 数 ,mathworks 提 供 的 文 档 上 面 讲 到 ,Matlab 的 图 形 库 只 有 在 用 mcc 生 成 可 执 行 程 序 (*.exe) 时 才 能 引 用 。 在 VC++的 程 序 中 直 接 使 用 Matlab 图 形 库 中 的 函 数 ( 例 如 mlfPlot) 是 不 背 支 持 的 。 另 外 , 在 使 用 mcc 生 成 DLL 的 时 候 , Matlab 图 形 库 中 的 函 数 也 不 是 全 部 都 测 试 过 。还 有 对 于 一 些 工 具 箱 中 的 函 数 , 如 果 用 到 一 些 数 学 库 之 外 的 函 数 , 就 有 可 能 出 现 错 误 。 即 使 编 译 通 过 , 在 运 行 的 时 候 也 有 可 能 出 错 。 但 是 , 随 着 Matlab 的 不 断 升 级 , mathworks 推 出 了 Matlab COM Builder 创 建 COM 组 件 , 对 这 种 不 兼 容 性 有 了 一 定 的 改 进 , 使 得 Matlab 和 高 级 语 言 的 混 合 编 程 变 得 越 来 越 实 用 , 越 来 越 简 单 。
参 考 文 献 :
[1] Matlab Compiler
[2] Matlab COM Builder