Matlab测试C函数模块
来源:互联网 发布:萧山网络问政平台临浦 编辑:程序博客网 时间:2024/06/05 03:51
Matlab测试C函数模块
matlab具有强大的数据处理和数据可视化能力,对于一些已经基本确定的c函数模块(不需要再单步调试找bug),又需要对数据进行一定分析处理(作图,拟合等)才能确定c函数模块的一些性能,那就合适使用matlab来测试c函数模块了。
1.1 软件环境
Windows 7 Service Pack 1Matlab版本2016a
VS版本VS professional 2015
其他版本的软件差别不大。
1.2具体步骤
1.2.1 matlab配置C编译器
Matlab命令行窗口里键入mex -setup,选择你要编译C++的编译器。第一次使用需要配置编译器,可能不同版本有偏差,按照提示配置就好。配置好了后会提示(在本文的环境下提示如下):
MEX 配置为使用 'Microsoft Visual C++ 2015 Professional (C)' 以进行 C 语言编译。
1.2.2 编写mex函数
mex文件是由matlab生成,其源文件是.c/.cpp文件。因此需要先将代码写成.c/.cpp文件。这里需要注意的是,mex源文件以C/C++语言格式书写(数组下标自0起,如果是纯C程序,还要记得在函数开始的时候声明所有变量),但是需要留出matlab这边的接口,即:(1)必须#include “mex.h”
#include “mex.h”
(2)主函数格式固定,作为接口,主函数内部可以调用其他的C函数:
void mexFunction(int nlts, mxArray *plhs[],
intnrhs, const mxArray * prhs[])
{
}
这里的参数包括:nlts 输出参数的个数;
plhs 输出参数的指针;
nrhs 输入参数的个数;
prhs 出入参数的指针;
(3)主函数的参数使用
获取指针:
p = mxGetPr(prhs[0]);
获取矩阵行数:
N = mxGetN(prhs[0]);
为输出矩阵分配空间:
plhs[0] = mxCreateDoubleMatrix(m, n, mxREAL);//plhs[0]为m×n的矩阵
需要说明的是,Matlab提供的API中,函数前缀有mex-和mx-两种。带mx-前缀的大多是对mxArray数据进行操作的函数,如mxIsDouble,mxCreateDoubleMatrix等等。而带mex前缀的则大多是与Matlab环境进行交互的函数,如mexPrintf,mexErrMsgTxt等等。了解了这一点,对在Apiref.pdf中查找所需的函数很有帮助。
需要注意的是,matlab矩阵数据的存储数据是“从上到下,从左到右”,即matlab里的A(i, j)在mex源文件里为A[ m * (j - 1) + i - 1]。这点需要留意。
1.2.3 VC调试(非必须)
matlab无法调试mex的源文件,只能检测语法错误(在编译的时候检查),但是对于数组越界这类内存泄露问题,matlab无法提供检查,而是强退(WTF?!)。因此最好现在VS下调试通过再到matlab下编译。在VS下编译mex源文件需要添加头文件及附加依赖项(类似于OpenCV的配置):(1)属性->C++目录->包含目录,加入MATLAB安装目录下的\extern\include 路径。
(2)属性->C++目录->库目录,加入MATLAB的\extern\lib\win64\microsoft 路径。
(3)属性->链接器->输入->附加依赖项,添加libmx.liblibeng.lib libmat.lib libmex.lib四个lib文件。
1.2.4 matlab编译mex文件
编辑好mex源文件后,在matlab下输入:mex 文件名(包含后缀),即可生成.mex(.mexw64)文件。这是就可以在matlab下直接调用C函数了,函数名就是文件名。
1.3 示例1:c语言与matlab单值传递
1.3.1 编写c实现文件和头文件
C函数add实现两个数的求和,在examle.c文件中定义如下/*example.c*/
/*Sum of two numbers*/
double add(doublea, doubleb)
{
returna + b;}
建立一个头文件myfunction.h中声明函数
/*mmyfunction.h*/
#ifndef MYFUNCTION_H_
#defineMYFUNCTION_H_
/*********************************
功能:计算两个数的和
参数:
a,第一个加数
b,第二个加数
返回值:
a,b的和。
*********************************/
#endif
1.3.2 编写mexFunction函数
/*test_add.c*/#include"mex.h"
#include"myfunction.h"
void mexFunction( intnlhs, mxArray *plhs[],
intnrhs, constmxArray *prhs[] )
{
double a=0;}
double b=0;
double *c;
/*Allocate memory for output,important!*/
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
/*get input value*/
a=mxGetScalar(prhs[0]);
b=mxGetScalar(prhs[1]);
/*get the adress of output plhs[0],and then can change the value
with c functions*/
c=mxGetPr(plhs[0]);
*c=add(a,b);
1.3.3 编译运行
(1)编译>> mex test_add.c example.c
生成名为test_add.mexw64的dll库,新版本的matlab生成的dll以mexwin64或mexwin32为后缀名。
可以看到,mexFunction是没返回值的,它不是通过返回值把结果传回Matlab的,而是通过对参数plhs的赋值。mexFunction的四个参数皆是说明Matlab调用MEX文件时的具体信息,如这样调用函数时(注意,函数名称与生成的.mexwin64文件同名):
(2)运行
>> c=test_add(1.2,2.5)
c =
3.7000
1.4 示例2:C语言与matlab二维数组(矩阵)专递
1.4.1 写好mexFunction接口
Matlab与C语言矩阵在内存中存储最大的区别是,所有Matlab阵列,不论其维数的大小在内存中,都是按照一维的方式存储,且在内存中是按照列的方式进行存储的。例如下面图1的2行5列的字符阵列,在内存中存储方式和线性索引表如图2所示。本文档主要使用Matlab来测试c模块,不应该对待测试的C函数有任何更改,matlab里使用m代码也不必考虑c语言的矩阵存储方式,因此对于matlab与c语言存在的一些数据处理的区别,必须在mexFunction函数里进行数据转换,以便可以专注于编写C程序和使用m程序处理测试结果。
图12行5列的字符阵列
图2 Matlab存储方式及其线性索引示意图
下面示例实现功能:在matlab定义一个矩阵,调用c程序对矩阵每个元素加上一个数x,然后返回矩阵到matlab。
1.4.2 编写c实现文件和头文件
/*example.c*/void addx(double *a, double *b, size_trow, size_tcolumn, doublex)
{
for (size_t i = 0; i <row; i++)
{
for (size_t j=0; j <column; j++)
*(b + i*column + j) = *(a + i*column + j) + x;
}}
头文件:
/*mmyfunction.h*/
#ifndef MYFUNCTION_H_
#defineMYFUNCTION_H_
void addx(double *a, double *b, size_trow, size_tcolumn, doublex);
#endif
1.4.3 编写mexFunction函数
注意matlab输入的矩阵要在mexFunction转换成c语言形式后,再传入c函数接口(这里是addx())。C函数接口传回来的矩阵,也要转换为matlab的形式,以便在matlab里使用。/*test_addx.c*/
#include"mex.h"
#include"myfunction.h"
void mexFunction(intnlhs, mxArray *plhs[],
intnrhs, constmxArray *prhs[])
{
double *a;
double *b;
double x;
/*Get the address of the input matrix*/
a = mxGetPr(prhs[0]);
size_t input_row = mxGetM(prhs[0]);//get input_row of metrix
size_t input_column = mxGetN(prhs[0]);//get input_column of metrix
mexPrintf("input_row=%d,input_column=%d\n", input_row, input_column);
double *c = (double *)malloc(input_row*input_column * sizeof(double));
/*The form of MATLAB is translated into C language form*/
for (size_t i = 0; i < input_row; i++)
{
for (size_t j = 0; j < input_column; j++)
{
*(c + i*input_column + j) = *(a + i + j*input_row);
}
}
/*Output two-dimensional array in C form*/
mexPrintf("输入参数:\n");
for (size_t i = 0; i < input_row; i++)
{
mexPrintf("\n ");
for (size_t j = 0; j < input_column; j++)
mexPrintf("%f ", *(c + i*input_column + j));
}
/*Get the address of the output matrix*/
b=mxGetPr(prhs[1]);
x = mxGetScalar(prhs[2]);
size_t output_row = input_row;//get output_row of metrix
size_t output_column = input_column;//get output_column of metrix
/*Allocate memory for output*/
plhs[0] = mxCreateDoubleMatrix((mwSize)output_row, (mwSize)output_column, mxREAL);
/*get the adress of output plhs[0],and then can change the value
with c functions*/
b=mxGetPr(plhs[0]);
double *d = (double *)malloc(output_row*output_column * sizeof(double));
addx(c,d,input_row,input_column,x);
/*The form of C language is translated into MATLAB*/
mexPrintf("\n输出参数:\n");
for (size_t i = 0; i < output_row; i++)
{
mexPrintf("\n");
for (size_t j = 0; j < output_column; j++)
{
*(b+ i+ j*output_row) = *(d + i*output_column + j);
mexPrintf("%f ", *(b + i + j*output_row));
}
}
free(c);
free(d);
}
1.4.4 编译运行
(1)编译>> mex test_addx.c example.c
(2)运行,建立一下test.m文件,调用addx函数接口
%test.m
a=[1,2,3,4,5;
6,7,8,9,10;
11,12,13,14,15]
b=zeros(3,5);
x=0.5;
c=test_addx(a,b,x)
>> test
a =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
input_row=3,input_column=5
输入参数:
1.000000 2.000000 3.000000 4.000000 5.000000
6.000000 7.000000 8.000000 9.000000 10.000000
11.000000 12.000000 13.000000 14.000000 15.000000
输出参数:
1.500000 2.500000 3.500000 4.500000 5.500000
6.500000 7.500000 8.500000 9.500000 10.500000
11.500000 12.500000 13.500000 14.500000 15.500000
c =
1.5000 2.5000 3.5000 4.5000 5.5000
6.5000 7.5000 8.5000 9.5000 10.5000
11.5000 12.5000 13.5000 14.5000 15.5000
1.5 示例3:C语言与matlab结构体传递
这需要把mxArray数据类型与结构体进行相互转换,较为复杂。每次测试的c模块的结构体往往不同,那么必须重新编写mxArray数据类型与结构体转换的函数模块。因此这里使用的方法是,不直接在matlab与c函数间进行数据传递,而是把数据按照一定格式写入txt文件,然后再进行读取。关于mxArray与结构体的转换可以参考这个博客:VC与Matlab混合编程(http://www.cnblogs.com/xpvincent/archive/2013/02/05/2893046.html)
1.6 小结
1.6.1 单值传递关键点
matlab ->c a = mxGetScalar(prhs[0]);//该函数获取matlab传递过来的数值;c ->matlab 有3步:
(1)plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);//为输出创建存储空间
(2) c = mxGetPr(plhs[0]);//获取返回plhs[0]的数据地址,其后可以修改y的值就可以返回了;
(3) *c=add(a,b);//调用C函数,把返回值赋给输出,传给matlab
1.6.2 二维数组(矩阵)传递关键点
在单值传递的基础上增加以下2步(1)matlab ->c,把输入矩阵转换为按行存储,再传递给C函数模块;
(2)c->matlab把C函数模块的输出矩阵转换为按行存储,再传递给Matlab。
1.6.3 结构体的传递
(1)可以通过编写mxArray和c结构体相互转换的函数来实现,需要熟练掌握对mxArray数据的操作。(2)把输入和输出数据写入txt文件来传递,本文采用此方法。
阅读全文
1 0
- Matlab测试C函数模块
- C调用MATLAB函数
- c 函数模块
- 时间模块常用函数测试
- Matlab调用C语言函数
- C/C++调用Matlab函数
- C 函数调用测试
- WFG测试函数的matlab版本
- Matlab mod函数 对应C语言 函数
- 模块测试函数基于linux2.6
- Matlab 模块库建立 S函数心得 小记
- MATLAB学习(五)MATLAB中调用C语言函数
- MATLAB与C++/MFC混合编程;调用MATLAB函数
- c 调用 matlab engine 自定义函数
- matlab中调用c语言函数
- MATLAB调用C/C++函数的方法
- matlab下如何调试c函数
- MATLAB调用C/C++函数的方法
- http://www.cnblogs.com/Jackie-zhang/p/6071769.html
- 旅游规划-Java
- 几种二叉树
- Android布局之线性布局
- npm-cli----Cannot find module 'D:\node\nodejs\node_module\bin\npm-cli.js'
- Matlab测试C函数模块
- Java知识--IO流操作(一)
- HDU 2036 G
- 安装Linux软件使用的命令:最好使用yum命令--而不是rpm.
- Nginx 使用总结
- HDU 3339 In Action 最短路+01背包
- 面试总结之抽象类与接口的对比
- 第6章 组件
- Java学习笔记-代理模式