matlab中加入C代码:matlab中安装C语言编译器TDM-GCC,编译、运行及mexFunction接口设置

通过把耗时长的函数用c语言实现,并编译成mex函数可以加快执行速度。Matlab本身是不带c语言的编译器的,所以要求你的机器上已经安装有VC,BC或Watcom C中的一种。

如果你在安装Matlab时已经设置过编译器,那么现在你应该就可以使用mex命令来编译c语言的程序了。。需要注意的是,较低版本的在设置编译器路径时,只能使用路径名称的8字符形式。

目录

1 编译器MinGW-w64安装

1.1 tdm-gcc下载:

1.2 tdm-gcc安装:

1.3 配置系统环境变量:

2 编写不带输入接口的C

2.1  C文件格式

2.2  m文件格式

2.3 程序运行

3 带输入参数的C

3.1 函数mexFunction接口规范

3.2 带输入参数的C

3.3 运行带参数的C

4 矩阵作为C的输入

4.1 矩阵在matlab和C中的不同

4.2 以矩阵作为输入时,nrhs的数据类型

5 带输出参数的C


1 编译器MinGW-w64安装

1.1 tdm-gcc下载:

http://tdm-gcc.tdragon.net/download

1.2 tdm-gcc安装:

点击exe文件进入安装界面——>将check for updated files一项取消勾选——>create时候建议——>一路下一步,完成安装。

1.3 配置系统环境变量:

电脑——>属性——>高级系统设置——>高级——> 环境变量——>系统变量——>新建:增加变量名MW_MINGW64_LOC,变量值为TDM-GCC-64的安装路径。

2 编写不带输入接口的C

2.1  C文件格式

为了测试设置正确与否,把下面的程序存为hello.c。

/*hello.c*/

#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{ 
    mexPrintf("hello,world!\n");
}

2.2  m文件格式

假设把hello.c放在了C:\TEST\下,并作为matlab的工作路径,在该路径下新建.m文件helloM.m。文件内容:

%% helloM.m

mex hello.c

hello

2.3 程序运行

执行该m文件,编译应该在出现编译器提示信息后正常退出,并生成一个新文件:hello.mexw64。现在键入hello(实际执行hello.mexw64),程序会在屏幕上打出一行:

hello,world!

3 带输入参数的C

3.1 函数mexFunction接口规范

分析hello.c,可以看到程序的结构是十分简单的,整个程序由一个接口函数 mexFunction构成。

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

nlhs :lhs-left hand side,说明调用语句左手面有nlhs个变量。

nrhs :rhs-right hand side,说明调用语句右手面有nrhs个自变量,由m文件调用时输入变量个数决定。

plhs :是一个指针数组,其内容为指针,该指针指向数据类型mxArray。
       若现在左手面只有一个变量(nlhs=1),即该数组只有一个指针,plhs[0]指向的结果会赋值给matlab中对应的变量。

prhs :是一个指针数组,指向m文件调用时输入的变量。
       若右手面有两个(nrhs=2)自变量(b,c),即该数组有两个指针,prhs[0]指向了b,prhs[1]指向了c。
       要注意prhs是const的指针数组,即不能改变其指向内容。

 

例如,使用

[a,b]=test(c,d,e)

调用mex函数test时,传给test的这四个参数分别是:

2,plhs,3,prhs

其中:

prhs[0]=c

prhs[1]=d

prhs[2]=e

当函数返回时,将会把你放在plhs[0],plhs[1]里的地址赋给a和b,达到返回数据的目的。

 

需要注意,prhs[i]和plhs[i]都是指向类型mxArray类型数据的指针。这个类型是在mex.h中定义的,事实上,在Matlab里大多数数据都是以这种类型存在。当然还有其他的数据类型,可以参考Apiguide.pdf里的介绍。

3.2 带输入参数的C

为了解参数传递的过程,把hello.c改写一下,使它能根据输入参数的变化给出不同的屏幕输出:

//hello.c 2.0

#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
       int *pin, in;
       pin = mxGetPr(prhs[0]);
       in = *(mxGetPr(prhs[0]));

       if(in==1)
              mexPrintf("hello,world!\n");
       else
              mexPrintf("大家好!\n");
}

3.3 运行带参数的C

将这个程序编译通过后,执行hello(1),屏幕上会打出:

hello,world!

而hello(0)将会得到:

大家好!

现在,程序hello已经可以根据输入参数来给出相应的屏幕输出。

4 矩阵作为C的输入

4.1 矩阵在matlab和C中的不同

通过mxGetPr只能得到指向这个矩阵的指针,如果我们不知道这个矩阵的确切大小,就没法对它进行计算。

为了解决这个问题,Matlab提供了两个函数mxGetM和mxGetN来获得传进来参数的行数 和列数。下面例程的功能很简单,就是获得输入的矩阵,把它在屏幕上显示出来:

//show.c 1.0
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double *inData;
    int M,N;
    int i,j;

    inData=mxGetPr(prhs[0]);
    M=mxGetM(prhs[0]);
    N=mxGetN(prhs[0]);
    // 打印输入矩阵
    printf("行:%d, 列:%d\n", M, N);
    for(i=0;i<M;i++) {
        for(j=0;j<N;j++)
            printf("%lf ",inData[i*N+j]);
        printf("\n");
    }
}

m文件输入以下内容:

a=1:12;

a = reshape(a,3,4)
mex show_1.c;
show_1(a)

会输出:

a =

     1     4     7    10
     2     5     8    11
     3     6     9    12

使用 'MinGW64 Compiler (C)' 编译。
MEX 已成功完成。
行:3, 列:4
1.000000 2.000000 3.000000 4.000000 
5.000000 6.000000 7.000000 8.000000 
9.000000 10.000000 11.000000 12.000000 

需要注意的是:mxGetM()获得matlab数组的行,mxGetN()获得matlab数组的列。但是在传递数组时需要注意matlab中与c中数组数据的表现形式的不同。

如上面数组在内存中按顺序依次存储:1,2,3,4,...,12
Matlab的数组变现3行4列:

     1     4     7    10
     2     5     8    11
     3     6     9    12

c中的数组格式若也要维持3行4列,依次取内存中的数据,填入数组中,则输出:

1.000000 2.000000 3.000000 4.000000 
5.000000 6.000000 7.000000 8.000000 
9.000000 10.000000 11.000000 12.000000 

4.2 以矩阵作为输入时,nrhs的数据类型

matlab中不需要定义数据类型,但C中需要确定的数据类型,因此C中接收matlab数据时,一般默认为double类型,下面对比不同之类类型接收数据的区别:

/*hello.c 2.1*/
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	int *pin;
    double *dpin;
	pin=mxGetPr(prhs[0]);
    dpin=mxGetPr(prhs[0]);
    
    mexPrintf("pin[1]:%d\n",pin[1]);
    mexPrintf("pin[1]:%f\n",dpin[1]);
}
%% 编译C
mex hello_2_1.c

a = [1,2,3];
b = [2,3,4];
%% 执行C
fprintf('------------\n')
hello_2_1(a)
fprintf('************\n')
hello_2_1(b)

运行m文件,输出结果:

------------
pin[1]:1072693248
pin[1]:2.000000
************
pin[1]:1073741824
pin[1]:3.000000

可见C中接收matlab的数据类型默认为double,即使matlab中传入的数据为整型。

5 带输出参数的C

输入数据是在函数调用之前已经在Matlab里申请了内存的,由于mex函数与Matlab共用同一个地址空间,因而在prhs[]里传递指针就可以达到参数传递的目的。但是,输出参数却需要在mex函数内申请到内存空间,才能将指针放在plhs[]中传递出去。由于返回指针类型必须是mxArray,所以Matlab专门提供了一个函数:mxCreateDoubleMatrix来实现内存的申请,函数原型如下:

mxArray *mxCreateDoubleMatrix(int m, int n, mxComplexity ComplexFlag)

m:待申请矩阵的行数
n:待申请矩阵的列数

为矩阵申请内存后,得到的是mxArray类型的指针,就可以放在plhs[]里传递回去了。但是对这个新矩阵的处理,却要在函数内完成,这时就需要用到前面介绍的mxGetPr。使用 mxGetPr获得指向这个矩阵中数据区的指针(double类型)后,就可以对这个矩阵进行各种操作和运算了。

//reverse.c 1.0

#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double *inData;
    double *outData1, *outData2;
    int M,N;
    int i,j;
    //异常处理
    if(nrhs!=1)
        mexErrMsgTxt("USAGE: [b,c]=reverse(a)\n");
    if(nlhs!=2)
        mexErrMsgTxt("USAGE: [b,c]=reverse(a)\n");
    if(!mxIsDouble(prhs[0]))
        mexErrMsgTxt("the Input Matrix must be double!\n");
    inData=mxGetPr(prhs[0]);
    M=mxGetM(prhs[0]);
    N=mxGetN(prhs[0]);
    // 打印输入矩阵
    printf("行:%d, 列:%d\n", M, N);
    for(i=0;i<M;i++) {
        for(j=0;j<N;j++)
            printf("%lf ",inData[i*N+j]);
        printf("\n");
    }
    // 每一行翻转
    plhs[0]=mxCreateDoubleMatrix(M,N,mxREAL);
    outData1=mxGetPr(plhs[0]);
    for(i=0;i<M;i++)
        for(j=0;j<N;j++)
            outData1[j*M+i]=inData[(N-1-j)*M+i];
    // 矩阵翻转
    plhs[1] = mxCreateDoubleMatrix(N,M,mxREAL);
    outData2 = mxGetPr(plhs[1]);
    for(i=0;i<N;i++)
        for(j=0;j<M;j++)
            outData2[i*M+j]=inData[i*M+j];
}

m文件内容如下:

a = 1:12;
a = reshape(a,3,4)

mex reverse.c
[b, c] = reverse(a)

在上面的异常处理中,使用了两个新的函数:mexErrMsgTxt和mxIsDouble。MexErrMsgTxt在给出出错提示的同时退出当前程序的运行。MxIsDouble则用于判断mxArray中的数据是否double类型。当然Matlab还提供了许多用于判断其他数据类型的函数,这里不加详述。

需要说明的是,Matlab提供的API中,函数前缀有mex-和mx-两种。带mx-前缀的大多是对mxArray数据进行操作的函数,如mxIsDouble,mxCreateDoubleMatrix等等。而带mx前缀的则大多是与Matlab环境进行交互的函数,如mexPrintf,mxErrMsgTxt等等。了解了这一点,对在Apiref.pdf中查找所需的函数很有帮助。

 

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Op_chaos

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值