您的位置:首页 > 编程语言 > MATLAB

C/C++与Matlab混合编程

2016-05-15 20:56 489 查看
由于实验室项目遗留问题,可能为了图matlab绘图方便,前面的开发人员在C++核心代码外加了一层matlab外壳,在matlab里调用C++方法,并使用matlab绘图显示。当我接手这份代码之后,在Windows上调试发现了几个难以忍受的问题,

1. matlab调用之前必须将c++代码编译成二进制文件,如此一来在matlab里就没法调试,不得不使用Visual Studio的附加进程调试,需要频繁来回切换VS和maltab;

2. 使用附加进程调试时如果C++程序崩溃,导致matlab必须重启,而matlab重启速度之慢无法忍;

3. 全速运行起来速度之慢无法忍。

综上所述,决定将代码全部移植到C++下。综合考虑,移植到C++下,可能存在以下两个问题:图像读取与转换和计算结果可视化

图像加载与转换

项目是有关图像处理的,matlab提供非常便捷的图像转换和处理库,在C++下没有这些API,也不可能自己从头实现这些基础功能,自然而然选择了OpenCV这样的第三方库。

下载OpenCV2.4.9 for Windows,解压到OPENCV_ROOT(自定义路径);

在VS2012里指定头文件路径为:
OPENCV_ROOT/build/include
;库文件路径:
OPENCV_ROOT/build/x64/vc11/lib


OPENCV_ROOT/build/x64/vc11/bin
拷贝
opencv_core249d.dll
,
opencv_core249.dll
,
opencv_highgui249d.dll
opencv_highgui249.dll
到VS工程目录(工程为x64,x86工程);

在代码中添加如下代码表明用到的库文件

#ifdef _DUBUG
#pragma comment(lib, "opencv_core249d.lib")
#pragma comment(lib, "opencv_highgui249d.lib")
#else
#pragma comment(lib, "opencv_core249.lib")
#pragma comment(lib, "opencv_highgui249.lib")
#endif


加载和显示图像

#include <opencv2\highgui\highgui.hpp>

int main(void){
cv::Mat img = cv::imread("test_image.jpg", CV_LOAD_IMAGE_GRAYSCALE);
cv::namedWindow("imageWindow");
cv::imshow("imageWindow", img);
cv::destroyWindow("imageWindow");
return 0;
}


可视化

项目最终有可视化的需求,而用C++做可视化成本太高,MATLAB在这方面独特的优势。在调试阶段应该使用尽可能方便的方法验证算法,于是决定在C++中调用MATLAB引擎绘图。MATLAB引擎函数库是MATLAB提供引擎方式接口的一系列程序的集合,它允许用户用自己的C/C++语言或FORTRAN语言应用程序中对MATLAB进行调用。
engine.h
头文件中定义了9个引擎函数。在VS2012里调用MATLAB引擎操作方式如下:

创建和MATLAB版本一致的C++工程,如,我的MATLAB是x64的,就创建x64的C++工程,这样才能保证调用的动态库版本正确;

在VS2012中添加MATLAB的头文件路径,如:
C:\Program Files\MATLAB\R2014a\extern\include
;添加库文件路径,如:
C:\Program Files\MATLAB\R2014a\extern\lib\win64\microsoft
,添加可执行文件路径,如:
C:\Program Files\MATLAB\R2014a\bin\win64
;

在代码中调用MATLAB引擎函数,为了使用方便,我对部分引擎函数做了一些封装,如下:

/*
* MatlabEngine.h
* this file is a C++ wrap of some MATLAB engine methods.
* it depends on the MATLAB installed on you machine.
* DATE: 2016.05.15
* AUTHOR: Lai Shaofa
* EMAIL: laishaofa@gmail.com
*/
# ifndef _MATLAB_ENGINE_H_
# define _MATLAB_ENGINE_H_

#include <stdio.h>
#include "engine.h"

#pragma comment(lib, "libeng.lib")
#pragma comment(lib, "libmx.lib")
#define     MAX_BUFFFER_SIZE (1024)

class MatlabEngine {

private:
Engine *ep;
char buffer[MAX_BUFFFER_SIZE];

public:
/*
* constructor: open matlab engine and set engine input/output buffer
*/
MatlabEngine(){
if ((ep = engOpen("")) == NULL)
{
fprintf(stderr, "\nCan't start MATLAB engine\n");
exit(1);
}
engOutputBuffer(ep, buffer, MAX_BUFFFER_SIZE);
}

/*
* destructor: close matlab engine
*/
~MatlabEngine()    {
engClose(ep);
}

/*
* matCreate: create a matrix
* @row: row of matrix
* @col: column of matrix
* NOTE: remember to call @matDestory to avoid memory leak
*/
mxArray* matCreate(const int32_t row, const int32_t col) {
assert(row>0 && col>0);
return mxCreateDoubleMatrix(row, col, mxREAL);
}

/*
* @matDestroy: destroy a matrix to release memory
* @mat: matrix to be destroyed.
*/
void matDestroy(mxArray* mat) {
assert(mat!=NULL);
mxDestroyArray(mat);
mat = NULL;
}

/*
* matPutVariable: put a variable to matlab engine with the name @matName
* @matName: name of variable,it used by matlab engine to identify the @mat
* @mat: matrix to be put
* @src: c/c++ source data pointer
* @size: size of source data
*/
void matPutVariable(const char* matName, const mxArray* mat, const void* src, const size_t size) {
assert(matName!=NULL);
assert(mat!=NULL);
assert(src!=NULL && size>0);
memcpy((void*)mxGetPr(mat), src, size);
engPutVariable(ep, matName, mat);
}

/*
* @matExecute: execute a matlab command in string format.
* @cmd: command string.
*/
void matExecute(const char * cmd) {
assert(cmd != NULL);
engEvalString(ep, cmd);
}

char* matGetOutput() {
return buffer;
}
};


4.在main函数中实例化引擎类并调用引擎方法:

#include <iostream>
#include "MatlabEngine.h"
using namespace std;

int main(void){
MatlabEngine engine;
double _x[] = { 1, 2, 3, 4, 5 };
double _y[] = {1, 4, 9, 16, 25};
mxArray* x = engine.matCreate(1, 5);
mxArray* y = engine.matCreate(1, 5);
engine.matPutVariable("x", x, _x, sizeof(_x));
engine.matPutVariable("y", y, _y, sizeof(_y));
engine.matExecute("plot(x, y, '-*b', 'linewidth', 1)");
engine.matExecute("grid on, axis equal");
engine.matDestroy(x);
engine.matDestroy(y);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: