C++调用MATLAB函数

MATLAB具有着很高的计算性能,一些算法用MATLAB很容易实现,而用C++很难实现,如果想在C++中调用MATLAB编写的函数,可以将该函数编译成库文件,之后在C++中对其进行调用。

本文详细讲解如何将MATLAB函数编译成库,并在C++中进行调用。方法可行,本人亲测。

第一步、在MATLAB中的命令行窗口中输入mex -setup,会出现如下界面。
在这里插入图片描述
第二步、点击界面中的“mex -setup C++”,出现如下提示。

在这里插入图片描述
第三步、之后就是进行对MATLAB中的function的编译了。这里,我的函数名为phasecong,实现的是图像相位一致性的计算。如下图所示。
在这里插入图片描述
这个函数是一位大牛学者写的,原本是有多个输入和多个输出的,但是为了编译方便和后续调用方便,我把其他几个参数删掉了,只保留了一个输入矩阵和一个输出矩阵。

这样做的好处是可以减少编译和调用出错的概率。编译方法见第四步。

第四步、下面就是对function进行编译了,编译的命令为:mcc -W cpplib:pc -T link:lib phasecong

这条命令中pc表示的是想要生成的库的名称,可以自己定,最后面的phasecong表示的是要编译的函数的名,注意函数名后面不要加.m后缀。其他的参数都不用改。

如下图所示。
在这里插入图片描述
第五步、输入完上面的命令后就是等待MATLAB编译完成了,我当时编译好像用了30秒左右的时间。

编译完成后就会出现编译成功的提示,如下图所示。

在这里插入图片描述
需要注意的是,在编译时,当前文件夹一定要为function所在的文件夹。

第六步、经过上面的编译后,在该文件夹下就会生成.h .cpp .lib .dll这四个文件,因为我设置的输出的库名称为pc,因此我这里生成pc.h pc.cpp pc.lib pc.dll这四个文件。
在这里插入图片描述
第七步、接下来就是将生成的这四个文件加入到我们的C++工程中了。

将这四个文件放在C++工程的文件夹中,最好在该文件夹中新建两个文件夹,分别命名为lib和include,因为后面我们还需要引入其他的库文件和头文件,这样做可以让文件更整齐。然后将pc.lib放入lib文件夹,将pc.h放入include文件夹。然后在VS中右键项目,点击属性,在属性中选择“配置属性”->“VC++目录”->“包含目录”,将刚才建立的include文件夹包含进去,如下图所示。其他的属性都不用改。
在这里插入图片描述
这样我们就将头文件包含了进去,之后进行加载lib文件,这里我们使用静态加载方式,在工程文件中加入这样一条语句:

#pragma comm#pragma comment(lib, ".\\lib\\pc.lib" )ent(lib, ".\\lib\\pc.lib" )

对于pc.dll和pc.cpp文件,值需要将其放在工程目录下就可以,不用进行配置。
这样就完成了对这四个文件的配置。

第八步、配置好生成的这四个文件后就可以运行C++的程序了,但是点击运行后应该会报错(通常一定会报错),不要怕,这是因为我们前面生成的这四个文件是需要依赖其他的库和头文件才能工作的。我们根据报错的信息可以知道缺少的头文件,例如下图这个错误:
在这里插入图片描述
通过这个错误我们就可以知道,我们的项目中缺少mat.h这个头文件,这时我们就要找到这个头文件并将其加入到include文件夹中。到哪里去找呢,在这个文件夹中“D:\Program Files\MATLAB\R2014b\extern\include”。重复这一操作,直到不再提示这种错误。这一操作需要重复很多次,像我这个项目需要加入下图这么多的头文件。

在这里插入图片描述
之后还需要加入额外的lib库文件,具体加入哪些lib文件,需要根据上面的这些头文件而定,我们到文件夹“D:\Program Files\MATLAB\R2014b\extern\lib\win64\microsoft”中(因为我的MATLAB是64位的,所以在win64文件夹下,如果大家的MATLAB是32位的,那么估计是在win32文件夹下,大家自己找一下),寻找上面这些头文件同名的lib文件,不过并不是每个头文件都能找到同名的lib文件,不过不要紧,我们只要把能找到的lib文件复制到工程目录下的lib文件夹中即可,除了这些lib文件之外,还需要加上“libmat.lib”和“libmx.lib”这两个文件,这两个文件好像包括着必要的类型的定义之类的吧。搞定之后我的lib文件夹中有下图这些个文件。

这些lib的加载方式与之前我们说的pc.lib的加载方式相同,如下图所示。
在这里插入图片描述
进行到此,我们所有的配置就都搞定了,如果没有意外的话,C++的项目编译就可以通过了,

但是虽然编译通过了,在运行的过程中还是有可能提示缺少某个库文件,我们只需要采用同样的方法把那些库文件加到项目里即可,比如我这个程序还提示我缺少mclmcr.dll这个文件,我就把这个文件复制到工程目录下就可以了,所需的dll文件通常都在“D:\Program Files\MATLAB\R2014b\bin\win64”这个文件夹可以找到。

至此我们就完成了MATLAB函数的编译和C++调用的整个过程。

最后是几点提示:

1、我这里使用的是MATLAB2014a和vs2013。

2、如果使用的MATLAB是64位的版本,那么C++的程序也要在x64下配置!!!!!!!

  如果使用的MATLAB是32位的版本,那么C++的程序也要在win32下配置!!!!!!

  这点非常重要!!!!!!!!

在这里插入图片描述
3、MATLAB函数的输入和输出参数通常都是矩阵,在C++中矩阵变量使用mwArray这个类型,这个类的使用方法可以看我下面贴的代码,也可以在网上找教程。

4、在C++程序中,我们调用这个函数的名称与MATLAB中定义的函数名称相同,这个函数是在MATLAB编译后生成的头文件中进行的声明,例如我这里是在pc.h中。

5、在C++程序中,在定义输入数组和输出数组时,最好使用动态数组,因为传统的数组是在栈中分配内存,这样会造成内存溢出。

最后为了更直观的展示在C++中如何对这些个库文件进行的调用以及如何使用这个函数,我在这里贴上了C++程序的源代码。

// pcproj.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "pc.h"
#include <iostream>
#include <fstream>

using namespace std;

#pragma comment(lib, ".\\lib\\pc.lib" )
#pragma comment(lib, ".\\lib\\mclmcrrt.lib")
#pragma comment(lib, ".\\lib\\libmx.lib")
#pragma comment(lib, ".\\lib\\libmat.lib")
#pragma comment(lib, ".\\lib\\mclmcr.lib")

#define WIDTH 512
#define HEIGHT 512

int _tmain(int argc, _TCHAR* argv[])
{
    //mclInitializeApplication(NULL, 0);
    //mclmcrInitialize();

    UINT8 *img_befor = new UINT8[WIDTH*HEIGHT];
    DOUBLE *img_after = new DOUBLE[WIDTH*HEIGHT];

    int data;
    double ddata;
    FILE *fp;

    errno_t err = fopen_s(&fp, "pixel.txt", "r");
    if (err!=0){
        cout << "open pic fail!" << endl;
        return 0;
    }

    for (int i = 0; i < WIDTH; i++){
        for (int j = 0; j < HEIGHT; j++){
            fscanf_s(fp, "%d", &data);
            img_befor[i*WIDTH + j] = data;
        }
    }

    fclose(fp);
    fp = NULL;

    pcInitialize();

    mwArray img_input_array(HEIGHT, WIDTH, mxUINT8_CLASS, mxREAL);
    mwArray img_output_array(HEIGHT, WIDTH, mxDOUBLE_CLASS, mxREAL);
    int nargout = 1;

    img_input_array.SetData(img_befor, HEIGHT*WIDTH);

    phasecong(nargout,img_output_array,img_input_array);

    img_output_array.GetData(img_after, HEIGHT*WIDTH);

    pcTerminate();

    //将结果写到文件
    err = fopen_s(&fp, "pixel_after.txt", "w");
    if (err != 0){
        cout << "open pic_after fail!" << endl;
    }
    else{
        //写文件
        for (int i = 0; i < WIDTH; i++){
            for (int j = 0; j < HEIGHT; j++){
                ddata = img_after[i*WIDTH + j];
                fprintf(fp, "%.4f ", ddata);
            }
            fprintf(fp, "\n");
        }
    }
    fclose(fp);
    fp = NULL;


    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值