MEX程序中的mexFunction函数【转】
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
把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[]);
if(i==)
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[]);
if(i[]==)
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[]); //获得指向矩阵的指针
M=mxGetM(prhs[]); //获得矩阵的行数
N=mxGetN(prhs[]); //获得矩阵的列数
for(i=;i<M;i++)
{ for(j=;j<N;j++)
mexPrintf("%4.3f ",data[j*M+i]);
mexPrintf("\n");
}
}
编译完成之后,用下面的命令测试一下:
a=:;
b=[a;a+];
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:待申请矩阵的列数
//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[]);
M=mxGetM(prhs[]);
N=mxGetN(prhs[]);
plhs[]=mxCreateDoubleMatrix(M,N,mxREAL);
outData=mxGetPr(plhs[]);
for(i=;i<M;i++)
for(j=;j<N;j++)
outData[j*M+i]=inData[(N--j)*M+i];
}
当然,Matlab里使用到的并不是只有double类型这一种矩阵,还有字符串类型、稀疏矩阵、结构类型矩阵等等,并提供了相应的处理函数。本文用到编制mex程序中最经常遇到的一些函数,其余的详细情况清参考Apiref.pdf。
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *inData;
double *outData;
int M,N;
//异常处理
//异常处理
if(nrhs!=)
mexErrMsgTxt("USAGE: b=reverse(a)\n");
if(!mxIsDouble(prhs[]))
mexErrMsgTxt("the Input Matrix must be double!\n");
inData=mxGetPr(prhs[]);
M=mxGetM(prhs[]);
N=mxGetN(prhs[]);
plhs[]=mxCreateDoubleMatrix(M,N,mxREAL);
outData=mxGetPr(plhs[]);
for(i=;i<M;i++)
for(j=;j<N;j++)
outData[j*M+i]=inData[(N--j)*M+i]; //总之,在C中,二维数组也是按照一维处理的
}
在上面的异常处理中,使用了两个新的函数: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[]); // 判断变量是否是数字
mxIsDouble(prhs[]); // 判断变量是否为双精度
mxIsEmpty(prhs[]); // 判断变量是否为空值
mxIsComplex(prhs[]); // 判断变量是否为复数
mexPrintf("%d", y); // 命令行中打印数据 x = mxGetN(prhs[]); // 获取输入参数的行数
y = mxGetM(prhs[]); // 获取输入参数的列数
points = mxGetScalar(prhs[]); // 将返回变量的实部,为双精度形数据
plhs[]= mxCreateDoubleMatrix(, , mxREAL); // 创建1×1双精度返回变量 x = mxGetData(prhs[]); // 获取变量的指针,功能相当于mxGetPr()
y = mxGetPr(plhs[]); // 获取变量的指针,数据为实数
if your c program is preparing a matrix for matlab, it need to be reshaped into one D
if your c program is getting data out of matlab, you need to convert yourself to become a meaningful data
但是在运算时必须按照1维的来运算,例如还是假设你输入的是4行5列的矩阵,你这里得到
int mBB = mxGetM(prhs[0]); // 行数mBB为4
int nBB = mxGetN(prhs[0]); // 列数nBB为5
double *bb = mxGetPr(prhs[0]); // 得到矩阵中数据的指针
这个时候如果你想调用原矩阵中3行2列的元素,即matlab中的bb(3,2),也即bb(4*(2-1)+3)也就是bb(7);那么在C中应该对应的是bb[mBB*(2-1)+(3-1)]也就是b[7-1],也就是bb[6](从这可以看出,是按照列数的)
MEX程序中的mexFunction函数【转】的更多相关文章
- 在一个C程序中,main()函数可以放在哪?
C语言规定,在一个C程序中,main()函数的位置(). A.必须在系统调用的库函数之后 B.必须在程序的开始 C.必须在程序的最后 D.可以在任意位置 答案:D [解析] 每个C程序有且只有一个主函 ...
- Linux上从Java程序中调用C函数
原则上来说,"100%纯Java"的解决方法是最好的,但有些情况下必须使用本地方法.特别是在以下三种情况: 需要访问Java平台无法访问的系统特性和设备: 通过基准测试,发现Jav ...
- MFC程序中消息以及函数的处理顺序简介[转]
MFC应用程序中处理消息的顺序 1.AfxWndProc() 该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc 2.AfxCallWndProc() 该 ...
- 从Win32程序中的主函数中获取命令行参数
在标准C或者Win32控制台程序的main函数中,它们都有两个参数:"argc" 和 "argv",如下所示: int main(int argc, char ...
- 小程序中使用async函数 会报 regeneratorRuntime is not defined的问题
async await比Promise更好的解决异步操作问题,但是在小程序中直接使用会出现以下的错误提示 是因为缺少了regeneratorRuntime这个模块,需要从外部引入 1.在新建的文件夹中 ...
- C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) .
我们在C语言编程中会遇到一些参数个数可变的函数,一般人对它的实现不理解.例如Printf(): Printf()函数是C语言中非常常用的一个典型的变参数函数,它 的原型为: int printf( c ...
- 程序中使用now()函数对性能的影响
这两天从某平台的慢查询日志中发现了一些很简单的,原本执行时间在0.01-0.03s的SQL,慢查询日志中记录的执行时间在2s左右. 排查后发现,表设计及索引建设均没有什么问题.但是SQL语句中使用了n ...
- 程序中图片透明 函数(使用SetBkColor API函数)
void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, short xStart, short yStart, COLORREF c ...
- PHP采集程序中的常用函数
随机推荐
- HDU 4418 Time travel
Time travel http://acm.hdu.edu.cn/showproblem.php?pid=4418 分析: 因为走到最后在折返,可以将区间复制一份,就变成了只往右走,01234321 ...
- 这样的SQL居然能执行
select /*! distinct cities.id from cities join countries on cities.id = countries.id limit 10 */;
- 【SpringCloud】 第十篇: 高可用的服务注册中心
前言: 必需学会SpringBoot基础知识 简介: spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选. ...
- Unity编辑器 - 资源修改立即写入磁盘AssetDataBase.SaveAssets()
Unity编辑器 - 资源修改立即写入磁盘AssetDataBase.SaveAssets() 在编写编辑器时,如果需要修改Unity序列化资源(如Prefab,美术资源,ScriptableObje ...
- angular-列表进行添加、编辑等操作时此行变色。
今天接触了一个功能,就是在一个列表中,当你新增或者对第N列进行编辑,删除等操作时这一列会变颜色.让用户对操作了哪行数据更认识更清晰,刷新之后这行的颜色就会消失.我觉得这个很有意思,记录一下.效果如下. ...
- Java反射篇学习笔记
今天重新学习了java中的反射,写一篇学习笔记总结一下.代码基本都是照着两篇博客敲的: 参考一: https://blog.csdn.net/sinat_38259539/article/deta ...
- commons-lang源码解析之StringUtils
apache的commons工具包是平时使用最多的工具包之一,对其实现方式需要具体了解.commons-lang version 3.1 empty和blank的区别 StringUtils中判断St ...
- yun rpm
RPM:RedHat Package Manager的简称,是一种数据库记录的方式的管理机制.当需要安装的软件的依赖软件都已经安装,则继续安装,否则不予安装. 特点:1.已经编译并打包完成2.软件的信 ...
- tensorflow学习笔记(3)前置数学知识
tensorflow学习笔记(3)前置数学知识 首先是神经元的模型 接下来是激励函数 神经网络的复杂度计算 层数:隐藏层+输出层 总参数=总的w+b 下图为2层 如下图 w为3*4+4个 b为4* ...
- jquery取radio单选按钮
// var strMess = '<%=Exchange() %>';// if (strMess == "兑换成功") {// ...