C++调用matlab数学函数问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++调用matlab数学函数问题相关的知识,希望对你有一定的参考价值。

下面是书上说的实现方法:

Visual C++中使用MATLAB语言C,C++数学函数库

MATLAB开发环境的C,C++数学函数库以mwArray结构体为数据核心,使用mcc命令将M文件转换成的C/C++文件可以直接在Viusal C++开发环境中使用,但是编译后的C,C++文件一般程序冗长,代码可读性较差。在熟练掌握C, C++数学函数库的基础上,读者可以使用mwArray结构体自行编写基于应用程序接口(API)函数库C, C++数学库的C/C++文件,可以极大优化程序代码,减少程序代码存储空间,提高程序代码的执行效率和执行速度。在下文的讲述中,将通过一个简单实例来演示如何利用mcc命令创建独立与MATLAB平台运行的exe文件。

首先使用MATLAB的M语言建立用户所需要的特定功能M 文件,在这里,为了简单而言,建立一个实现魔方阵功能的M文件magicCreat.m。

function y = magicCreat(n)
y = magic(n)

然后从%matlabroot%\ extern\examples\compiler (%matlabroot%为读者计算机系统中MATLAB的安装路径,本文中为

C:\Program Files\MATLAB\R2006a\extern\examples\compiler)

路径下拷贝main_for_lib.c和main_for_lib.h.到当前的工作路径下,以便mcc编译命令调用。然后创建调用magicCreat.m文件的C语言程序如下:

#include "stdio.h"
#include "math.h"
#include "libPkg.h" //编译建立的库头文件
main( int argc, char **argv )

mxArray *N; /* 输入变量矩阵指针 */
mxArray *R = NULL; /* 结果矩阵指针 */
int n; //默认的M文件输入变量数值
/* 获取命令行参数,如果命令行输入小于2,则输入参数默认为5 */
if (argc >= 2)
n = atoi(argv[1]);
else
n = 5;

//初始化MCR和libPkg函数库
mclInitializeApplication(NULL,0);
libPkgInitialize();
/* 得到输入参量的数值 */
N = mxCreateDoubleScalar(n);
/*调用magicCreat.m编译后的文件mlfMagicCreat*/
mlfMagicCreat(1, &R, N);
/* 释放内存空间*/
mxDestroyArray(N);
mxDestroyArray(R);
//结束libPkg库和MCR
libPkgTerminate();
mclTerminateApplication();


其中libPkg.h为mcc命令编译后的库文件。该文件结构清晰,首先程序代码包含相关必要的头文件和libPkg.h文件,主程序入口,变量的定义,然后初始化MCR和libPkg函数库,调用magicCreat.m编译后的文件mlfMagicCreat,调用结果用矩阵R存储,最后释放内存空间,并结束libPkg库和MCR。在程序结束之前及时地释放内存空间是一个很好的编程习惯。将该程序存储为magicCreatCFile.c,接下来使用mcc命令编译该文件,在MATLAB命令行窗口中输入:

mcc -W lib:libPkg -T link:exe magicCreat magicCreatCFile.c main_for_lib.c

经过mcc命令编译后,可以发现在当前路径下,出现一个magicCreat.exe文件,为一个可执行程序文件,在MATLAB命令行窗口输入:
>> !magicCreat

Extracting CTF archive. This may take a few seconds, depending on the
size of your application. Please wait...
...CTF archive extraction complete.
y =

17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9

程序正常运行,由于命令行输入变量个数小于2,因此M文件输入参数默认值为5,程序产生一个5阶的魔方阵,如果需要输入第2个输入参数,则可以按照以下方式在MATLAB命令行窗口中输入:
>> !magicCreat 3 %创建一个3阶的魔方阵

y =

8 1 6
3 5 7
4 9 2

但是 在%matlabroot%\ extern\examples\compiler 下面找不到说说的文件……链接libPkg.h出错……

麻烦解决下

20分先放这,会追加的~~

参考技术A 楼主的matlab是哪版,貌似05b以后就不能在c中直接调用MATLAB数学函数库了。
能用的只有在c中创建一个matlab engine,通过调用engine实现条用相应的数学函数。不过很慢,不建议使用。
参考技术B 怎么会找不到呢?安装目录找对了吗?我的目录是:
D:\program files\MATLAB\R2007a\extern\examples\compiler本回答被提问者采纳
参考技术C 搜索该头文件,复制到你的工程中去,然后添加。再编译试试。

使用带有 MEX Wrapper 的辅助 C 文件从 MATLAB 2016 调用 C++ 代码时遇到问题

【中文标题】使用带有 MEX Wrapper 的辅助 C 文件从 MATLAB 2016 调用 C++ 代码时遇到问题【英文标题】:Trouble calling C++ code from MATLAB 2016 using a helper C file w/MEX Wrapper 【发布时间】:2019-05-30 20:11:47 【问题描述】:

我需要从 MATLAB 2016 调用 C++ 非成员函数。MATLAB 直到 2018 年才支持 C++ MEX,所以这会产生问题。

我在 mingw64 下的 Windows 中执行此操作。

为了解决这个问题,我尝试使用 MEX 包装器制作一个 C 文件,其中 C 实现纯粹只是根据网上的一些建议使用带有 extern "C" 的共享头文件调用 C++ 函数。

但是,我对 MATLAB 非常陌生,在这里从 C 和其他一些概念调用 C++。所以没有任何东西可以正确编译。

非常感谢任何有关正确处理此问题的建议。

头文件myFunc.h:

#ifndef CPP_H
#define CPP_H

#ifdef __cplusplus
void myFunc(const std::vector<myStruct>& a,
            const std::vector<myStruct>& b,
            const double c,
            std::vector<std::pair>& d,
            mxArray **e
            );
extern "C" 
#endif
void myFunc(const std::vector<myStruct>& a,
            const std::vector<myStruct>& b,
            const double c,
            std::vector<std::pair>& d,
            mxArray **e
            );
#ifdef __cplusplus

#endif

#endif

调用它的 C 文件,myFuncCaller.c:

#include "myFunc.h"
#include "mex.h"

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

    myFunc(prhs[0], prhs[1], prhs[2], prhs[3], prhs[4]);

实际实现:myFunc.cpp:

#include "myFunc.h"

void myFunc(const std::vector<myStruct>& a,
            const std::vector<myStruct>& b,
            const double c,
            std::vector<std::pair>& d,
            mxArray **e
            )

  //things done here, pushes results to d

尝试编译这两者的最终结果是:

C 文件看不到 mex.h(不确定原因,因为 MATLAB 声称 mingw 是投诉) 头文件可能全错,并声称“类型默认为 int 在 std 声明中”。我假设这是因为我在 C 部分中有一些与 C++ 相关的东西。我不知道如何解决这个问题。 C++ 文件抱怨最多。我可以发布所有错误,但考虑到我的逻辑可能存在根本缺陷,我认为这不会有成效。

一个很大的障碍是从 MATLAB -> C -> C++ 传递输入参数的方法。我不希望事情“丢失”,并且除非必要,否则最好不要进行转换,而且我不确定那会在哪里。

【问题讨论】:

需要注意的一点(但可能不是这里唯一缺少的)prhs[0], prhs[1], ... 的类是*mxArray,但你的函数需要std::vector,所以你必须这样做转换。如果您使用 C++ MEX API,输入将是 matlab::data::Array 填充在 matlab::mex::ArgumentList 内。 由于我使用的是 MATLAB 2016,遗憾的是没有 C++ MEX API,否则我会使用这些 API。正在努力解决这个问题。 【参考方案1】:

    您不能将 std::vector&lt;&gt; 放在 extern "C" 部分中,因为它不是有效的 C 语法。您需要创建一个纯 C 函数存根,编译为 C++,调用 C++ 函数。

    但是,您无需执行任何操作,因为您可以很好地编译 C++ MEX 文件。 API 是 C,但您可以毫无问题地从 C++ 调用 C 函数。

    您的mexFunction 中的实际问题是您将指针传递给mxArray 对象,其中函数期望引用std::vector&lt;&gt; 等。做到这一点的唯一方法是从MATLAB 复制数据将数组转换为 C++ 向量:

#include "myFunc.h"
#include "mex.h"

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

   if (nrhs < 5) 
      mexErrMsgTxt("Not enough input arguments! 5 expected.");
   

   // arg 1: std::vector<myStruct>
   if (!mxIsDouble(prhs[0])) 
      mexErrMsgTxt("First input argument must be a double array.");
   
   std::size_t N = mxGetNumberOfElements(prhs[0]);
   double* pr = mxGetPr(prhs[0]);
   std::vector<myStruct> a(N);
   std::copy(pr, pr+N, a.begin());

   // arg 2: std::vector<myStruct>
   std::vector<myStruct> b; 
   // ...

   // arg 3: double
   double c = mxGetScalar(prhs[2]);

   // arg 4: std::vector<std::pair> // This makes no sense in C++, std::pair<> is a template, 2 template arguments missing!!
   std::vector<std::pair> d;
   // ...

   // arg 5: mxArray **  // is this the output? Why does your C++ function take an mxArray?

   myFunc(a, b, c, d, &prhs[4]);

【讨论】:

对于上下文,它不是专门的 std::pair ,而是使用该模板的东西。我应该更清楚。它是一对无符号整数。此外, mxArray 实际上并不是输出。如果有的话,参数 4(对)将是输出,因为它是指向一个向量的指针,该向量应该由函数使用 push_back 填充。我将查看此代码和您的回复,我认为这可能是我解决问题的途径。谢谢。 @Tyler:如果你可以改变myFunc,你可以不复制地传递MATLAB数据。您必须有一个 double* 和一个 std::size_t 输入参数,而不是每个 std::vector 我可以随心所欲地修改 myFunc,除了它需要什么参数。这些必须保持不变。 (它是一个更大的软件开发项目的一部分,依赖/使用未来可能会改变的特定用户定义数据类型) 我遇到了一个找不到 mex.h 的问题。我会再发一个问题,所以我可能要过几天才能回复这个原帖,让你知道我的努力是否成功。 @Tyler:您是否在 MATLAB 中使用mex 命令编译 MEX 文件?用gcc编译比较难,很多东西都需要设置的恰到好处。如果您使用mex 命令,但找不到mex.h,则可能需要先运行mex -setup

以上是关于C++调用matlab数学函数问题的主要内容,如果未能解决你的问题,请参考以下文章

备战数学建模2-MATLAB中顺序,选择,循环及函数的应用

转C++调用Matlab的.m文件

C++:隐藏一些函数

备战数学建模4-MATLAB绘制三维图形

matlab中的reshape命令有啥数学意义?

Matlab——系统预定义的变量 常用数学函数