如何在Matlab代码中使用C代码

一、为什么在Matlab中使用C

  1. 性能优化:C语言提供了接近硬件的编程能力,使得开发者可以编写高效率的代码。对于计算密集型任务,尤其是那些需要大量数值计算的场景,用C语言编写的函数通常比MATLAB内置函数运行得更快。这是因为C语言允许更细致地控制内存使用和处理器指令。
  2. 现有代码库的利用:在某些领域,已有大量用C或C++编写的成熟、高效的代码库。通过MEX接口,MATLAB可以直接调用这些代码库,无需重写这些功能。这样不仅可以节省开发时间,还能确保使用经过验证的、高质量的代码。
  3. 扩展MATLAB功能:虽然MATLAB提供了广泛的函数库,但在某些特定应用领域,用户可能需要一些MATLAB本身不提供的特殊功能。通过使用C语言,开发者可以创建自定义的MEX文件来扩展MATLAB的功能,满足特定的需求。
  4. 硬件接口:在需要与硬件设备(如传感器、仪器或其他外部设备)直接交互时,C语言提供了访问底层硬件接口的能力,例如通过串口或网络接口。通过在MATLAB中集成C语言编写的代码,用户可以实现对这些设备的控制和数据采集。
  5. 跨平台兼容性:C语言具有很好的跨平台兼容性,编写的代码可以在不同操作系统上编译运行,这对于需要在多个平台上部署MATLAB应用的场景非常有用。
  6. 专业算法实现:对于一些高度专业化的算法,可能只有少数专家知道如何高效实现。这些专家可能习惯于使用C语言,因此他们编写的高效算法往往以C语言的形式存在。将这些算法通过MEX接口集成到MATLAB中,可以让更广泛的用户受益。

二、MEX重要接口概览

mex.h是MATLAB提供的一个头文件,专为MEX文件开发而设计。它包含了一系列的宏定义、类型定义和函数原型,这些都是在C或C++代码中与MATLAB数据进行交互所必需的。通过这些接口,开发者可以创建MEX文件,这些文件能够直接从MATLAB环境中被调用

以下是mex.h中提供的一些重要接口的概览:

  1. 内存管理

    • mxMallocmxCallocmxReallocmxFree:这些函数用于在MEX文件中分配和释放内存,类似于标准C库中的malloccallocreallocfree
  2. 错误处理

    • mexErrMsgIdAndTxtmexWarnMsgIdAndTxt:这些函数用于在MEX函数执行过程中显示错误或警告信息,并且可以选择性地终止MEX文件的执行。
  3. MATLAB数据访问和创建

    • mxCreateDoubleMatrixmxCreateNumericArraymxCreateCharArray等:这些函数用于创建各种类型的MATLAB数据结构(如矩阵、数组等)。
    • mxGetPrmxGetPimxGetDatamxGetScalar等:这些函数用于访问MATLAB数据结构中的实际数据。
    • mxSetPrmxSetPimxSetData等:这些函数用于设置MATLAB数据结构中的数据。
  4. 数据属性查询

    • mxGetMmxGetNmxGetNumberOfElementsmxGetClassID等:这些函数用于查询MATLAB数组的维度、元素数量、数据类型等属性。
  5. 类型检查和转换

    • mxIsDoublemxIsSinglemxIsClass等:这些函数用于检查MATLAB数组的数据类型。
    • mxGetClassID:获取MATLAB数组的类别。
  6. MEX文件入口点

    • mexFunction:所有MEX文件都必须定义这个函数,它是MEX文件的入口点,MATLAB调用MEX文件时就是通过这个函数。
  7. 调用MATLAB函数

    • mexCallMATLAB:允许MEX文件中的代码调用MATLAB中的函数。

三、一个小例子

3.1、装入编译器

可以看到可以选两种编译器,一种是 C++ 另一种是 FORTRAN

请添加图片描述

3.2、写C函数

在同一目录下,创建一个 ADD.c 文件,其函数形式必须是

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

其中

  • nlhs:输出参数个数
  • plhs:输出参数列表
  • nrhs:输入参数个数
  • prhs:输入参数列表

保存的文件名就是将来在MATLAB中调用的函数名,而不是这里的函数名。

下面给出一个例子,其中输入是两个矩阵,返回一个矩阵,实现矩阵中元素的相加。

#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    if(nrhs <1) {
       mexPrintf("input param count error\n");
       return;
    } 
    int rowNum1 = mxGetM(prhs[0]);                                        // 获得第一个矩阵的行数
    int colNum1 = mxGetN(prhs[0]);                                        // 获得第一个矩阵的列数
    double* pArr2 = (double*)mxGetPr(prhs[0]);                            // 获得第一个矩阵的指针,这里是一维的 
    
    int rowNum2 = mxGetM(prhs[1]);                                        // 获得第二个矩阵的行数
    int colNum2 = mxGetN(prhs[1]);                                        // 获得第二个矩阵的列数
    double* pArr2 = (double*)mxGetPr(prhs[1]);                            // 获得第二个矩阵的指针,这里是一维的 

    if (rowNum1 != rowNum2 || colNum2 != colNum2) {                       // 保证两个矩阵同纬度
        mexPrintf("two matrix is different size\n");
    }

    
    plhs[0] = mxCreateDoubleMatrix(rowNum1, colNum1, mxREAL);             // 创建返回矩阵
    double* retValue = mxGetPr(plhs[0]);                                  // 创建返回矩阵的执政
    for(int i=0;i<rowNum1*colNum1;i++) { 
        retValue[i] = pArr1[i] + pArr2[i];                                // 填充数据
    }
    return; 
}
res = ADD([1,2],[3,4])

我们编译一下,编译指令 mex ADD.c

请添加图片描述

3.3、一些问题

问:我们传入的是一个二维矩阵,为什么从C代码中确实一个一维指针指向了存储的数据?

答: 在C中处理从MATLAB传入的二维矩阵时,您通常会通过mxGetPr函数获得一个指向矩阵第一个元素的指针。这个指针可以被视为指向一个一维数组的指针,而不是直接作为二级指针。因为MATLAB矩阵在内存中是按列主序(column-major)存储的,所以即便我们想要像操作二维数组那样操作它们,也需要一些额外的步骤来正确地索引这个数组。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LyaJpunov

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

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

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

打赏作者

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

抵扣说明:

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

余额充值