MEX程序中的mexFunction函数【转】

与C中的main函数一样,MEX程序中的开始函数为mexFunction.默认变量参数是:

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

其中

nlhs输出参数数目

plhs[]指向输出参数的指针

nrhs输入参数的数目

prhs[]指向输入参数的指针

例如:使用[a,b]=test(c,d,e)

调用mex函数test时,传给test的这三个参数分别是prhs[0]=c ,prhs[1]=d ,prhs[2]=e

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

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


//hello.c 2.0
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int i;
i=mxGetScalar(prhs[0]);
if(i==1)
mexPrintf("hello,world!\n");
else
mexPrintf("大家好!\n");
}

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

大家好!
现在,程序hello已经可以根据输入参数来给出相应的屏幕输出。在这个程序里,除了用到了屏幕输出函数mexPrintf(用法跟c里的printf函数几乎完全一样)外,还用到了一个函数:mxGetScalar,调用方式如下:

i=mxGetScalar(prhs[0]);
"Scalar"就是标量的意思。在Matlab里数据都是以数组的形式存在的,mxGetScalar的作用就是把通过prhs[0]传递进来的mxArray类型的指针指向的数据(标量)赋给C程序里的变量。这个变量本来应该是double类型的,通过强制类型转换赋给了整形变量i。既然有标量,显然还应该有矢量,否则矩阵就没法传了。看下面的程序:


//hello.c 2.1
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
int *i;
i=mxGetPr(prhs[0]);
if(i[0]==1)
mexPrintf("hello,world!\n");
else
mexPrintf("大家好!\n");
}

这样,就通过mxGetPr函数从指向mxArray类型数据的prhs[0]获得了指向double类型的指针。
但是,还有个问题,如果输入的不是单个的数据,而是向量或矩阵,那该怎么处理呢
?通过mxGetPr只能得到指向这个矩阵的指针,如果我们不知道这个矩阵的确切大小,就
没法对它进行计算。

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


//show.c 1.0
#include "mex.h"
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *data;
int M,N;
int i,j;
data=mxGetPr(prhs[0]); //获得指向矩阵的指针
M=mxGetM(prhs[0]); //获得矩阵的行数
N=mxGetN(prhs[0]); //获得矩阵的列数
for(i=0;i<M;i++)
{ for(j=0;j<N;j++)
mexPrintf("%4.3f ",data[j*M+i]);
mexPrintf("\n");
}
}

编译完成之后,用下面的命令测试一下:

 a=1:10;
b=[a;a+1];
show(a)
show(b)

需要注意的是,在Matlab里,矩阵第一行是从1开始的,而在C语言中,第一行的序数为0,Matlab里的矩阵元素b(i,j)在传递到C中的一维数组大data后对应于data[j*M+i]。

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

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

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

为矩阵申请内存后,得到的是mxArray类型的指针,就可以放在plhs[]里传递回去了。但是对这个新矩阵的处理,却要在函数内完成,这时就需要用到前面介绍的mxGetPr。使用mxGetPr获得指向这个矩阵中数据区的指针(double类型)后,就可以对这个矩阵进行各种操作和运算了。下面的程序是在上面的show.c的基础上稍作改变得到的,功能是将输入矩阵进行上下翻转


//reverse.c 1.0
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
double *inData;
double *outData;
int M,N;
int i,j;
inData=mxGetPr(prhs[0]);
M=mxGetM(prhs[0]);
N=mxGetN(prhs[0]);
plhs[0]=mxCreateDoubleMatrix(M,N,mxREAL);
outData=mxGetPr(plhs[0]);
for(i=0;i<M;i++)
for(j=0;j<N;j++)
outData[j*M+i]=inData[(N-1-j)*M+i];
}

当然,Matlab里使用到的并不是只有double类型这一种矩阵,还有字符串类型、稀疏矩阵、结构类型矩阵等等,并提供了相应的处理函数。本文用到编制mex程序中最经常遇到的一些函数,其余的详细情况清参考Apiref.pdf。

通过前面两部分的介绍,大家对参数的输入和输出方法应该有了基本的了解。具备了这些知识,就能够满足一般的编程需要了。但这些程序还有些小的缺陷,以前面介绍的re由于前面的例程中没有对输入、输出参数的数目及类型进行检查,导致程序的容错性很差,以下程序则容错性较好


#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *inData;
double *outData;
int M,N;
//异常处理
//异常处理
if(nrhs!=1)
mexErrMsgTxt("USAGE: b=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]);
plhs[0]=mxCreateDoubleMatrix(M,N,mxREAL);
outData=mxGetPr(plhs[0]);
for(i=0;i<M;i++)
for(j=0;j<N;j++)
outData[j*M+i]=inData[(N-1-j)*M+i];
}

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

需要说明的是,Matlab提供的API中,函数前缀有mex-和mx-两种。带mx-前缀的大多是对mxArray数据进行操作的函数,如mxIsDouble,mxCreateDoubleMatrix等等。而带mx前缀的则大多是与Matlab环境进行交互的函数,如mexPrintf,mxErrMsgTxt等等。了解了这一点,对在Apiref.pdf中查找所需的函数很有帮助。
至此为止,使用C编写mex函数的基本过程已经介绍完了。

在函数内部调用时,常用函数用法如下:


mxIsNumeric(prhs[0]); // 判断变量是否是数字
mxIsDouble(prhs[0]); // 判断变量是否为双精度
mxIsEmpty(prhs[0]); // 判断变量是否为空值
mxIsComplex(prhs[0]); // 判断变量是否为复数
mexPrintf("%d", y); // 命令行中打印数据

x = mxGetN(prhs[0]); // 获取输入参数的行数
y = mxGetM(prhs[1]); // 获取输入参数的列数
points = mxGetScalar(prhs[1]); // 将返回变量的实部,为双精度形数据
plhs[0]= mxCreateDoubleMatrix(1, 1, mxREAL); // 创建1×1双精度返回变量

x = mxGetData(prhs[0]); // 获取变量的指针,功能相当于mxGetPr()
y = mxGetPr(plhs[0]); // 获取变量的指针,数据为实数

对mexFunction的参数是进行指针操作的,不能用单纯的return返回值。MEX程序传送回来的整数数据要变为双精度型数据,才能为其它函数所处理。

http://blog.sina.com.cn/s/blog_492dbb6b0100arl2.html

MEX程序中的mexFunction函数【转】,布布扣,bubuko.com

时间: 2024-10-06 19:01:44

MEX程序中的mexFunction函数【转】的相关文章

高压同步机VF程序中的 sub_VoltandCurrent_Tans() 函数

高压同步机VF程序中的 sub_VoltandCurrent_Tans() 函数 2016-12-11 10:40 120人阅读 评论(0) 收藏 举报  分类: 程序备忘(42)  版权声明:本文为博主原创文章,可以转载 if(MOTOR_TYPE==1)//电励磁同步电机     {    sub_VoltandCurrent_Tans();    /*对I_a(Ias),I_b(Ibs),Uan,Ubn进行clark,park变换,    (其中Uan,Ubn由电压重构求得)    求得I

MFC程序中消息以及函数的处理顺序简介[转]

MFC应用程序中处理消息的顺序 1.AfxWndProc()      该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc 2.AfxCallWndProc()  该函数负责保存消息(保存的内容主要是消息标识符和消息参数)供应用程序以后使用,                    然后调用WindowProc()函数 3.WindowProc()      该函数负责发送消息到OnWndMsg()函数,如果未被处理,则调用DefWindowProc()函数 4.

Linux上从Java程序中调用C函数

原则上来说,"100%纯Java"的解决方法是最好的,但有些情况下必须使用本地方法.特别是在以下三种情况: 需要访问Java平台无法访问的系统特性和设备: 通过基准测试,发现Java代码比其他语言编写的等价代码慢得多: 其他语言编写的代码已经经过大量测试和调试,并且知道如何将其导出到所有的目标平台上. Java平台有一个用于和本地C.C++代码进行互操作的API,称为Java本地接口(JNI).下面将举例讨论Linux平台下的JNI编程. 1. 创建java类文件 创建一个native

在C程序中使用系统调用函数 rename()

1 查看系统调用函数的信息 2 编写代码 3 测试编译程序 ·············· 1 查看系统调用函数的信息 查看系统调用函数 rename() 的信息.寻找函数使用方法,函数返回值情况. # man 2 rename 函数有两个实参,是两个字符指针(常量):原始文件名在前,新文件名在后. 成功执行后返回值是 "0". 头文件是 "stdio.h" 2 编写代码 vim changename.c gcc -o cn changename.c strip cn

PHP采集程序中的常用函数

LOL游戏程序中对一些函数的Hook记录(Win10 x64)

[PC Hunter Standard][League of Legends.exe-->Ring3 Hook]: 108Hooked Object Hook Address and Location Type Current Value Original Value[*]len(4) League of Legends.exe 0x0000000000AC6785->_ inline C7 86 20 01 00 00 00 00[*]len(4) League of Legends.exe

把一下程序中的print()函数改写成

源代码: #include <iostream> using namespace std; void print( int w ) { for( int i = 1 ; i <= w ; i++ ) { for( int j = 1 ; j <= i ; j++ ) cout << i << " " ; cout << endl ; } } int main() { print( 5 ) ; } 错误代码: //错误代码 #i

MATLAB中mexFunction函数的接口规范(转载)

MEX文件的调用极为方便,其调用方式与MATALAB的内建函数完全相同,只需要在命令窗口内输入对应的文件名称即可. C语言MEX程序代码文件有计算子例程(Computational routine)和接口子程序(GatWay routine)两个相互独立的子程序组成.其中,计算子例程的功能是完成所需要的计算,它和具有相同功能的一般C源程序文件相同:接口子程序的功能则是计算子程序和MATALAB的接口,用户实现两个不同内存空间中的通信. void mexFunction(int nlhs, mxA

SUID或SGID程序中能不能用system函数

system()函数的声明和说明如下: 注意它的描述那里,system()执行一个由command参数定义的命令,通过调用/bin/sh -c命令来实现这个功能.也就是说它的逻辑是这样的! 进程调用system函数,system函数调用fork创建一个子进程,然后再调用exec函数来把这个子进程的正文段替换成/bin/sh命令的正文段.然后再由sh来执行exec将程序的正文段替换成command参数所代表的命令的正文段,例如,我的一个程序a.out来调用system函数来执行sleep 20命令