MATLAB与C++/MFC混合编程;调用MATLAB函数

来源:互联网 发布:深圳单片机解密 编辑:程序博客网 时间:2024/05/22 02:21

MATLAB与C++/MFC混合编程;调用MATLAB函数

因为项目需要,前期工作一直在VS2013(编译平台Win32)与MATLAB2014a(64bit)两个平台进行,VS2013用来生成数据,MATLAB2014a用来处理数据,为了简化过程便于应用,想将MATLAB的数据处理程序移植成C++代码,但是发现C++处理数据远没有MATLAB方便,便开始百度“C++/MFC调用MATLAB函数”,惊奇发现原来还有MATLAB与C++混合编程这么回事。但是按照网上教程配置环境始终不能成功,搞了好几天,逛论坛、找人请教才终于解决。_**本文先参考网上教程配置编程环境,再针对我遇到的问题给出解决方案。**1.MATLAB环境配置打开MATLAB,在命令行输入:mex -setup,回车,选择已安装的vc编译器

这里写图片描述

依次点击mex -setup C++ 和Microsoft Visual C++ 2013 Professional(根据自己情况)后看到以下提示:

这里写图片描述
然后继续在命令行中输入:mbuild -setup ,按照上述类似的方式设置编译器。

2. 新建m文件建议从简单函数入手,这样会容易找到后续编译不成功的问题。
    function C=Add(A,B)                C=A+B;    end
保存为Add.m文件。3. 创建动态链接库Matlab命令行中输入:mcc -W cpplib:libAdd -T link:lib Add回车后出现错误提示:**Test checkout of feature 'Compiler' failed**,百度后知道是MATLAB破解不完全,于是找了个matlab R2014a fully crack,破解MATLAB编译器。重启后继续输入上面的命令,等待编译完成。

这里写图片描述

将.h、.lib、.dll文件拷贝到VS工程目录下。4. 系统环境配置Computer - > Properties -> Advanced system settings -> Environment Variables -> User Variables -> path, 添加("MATLAB"为MATLAB 2014a软件安装目录)

…\MATLAB\extern\lib\win32\microsoft;
…\MATLAB\bin\win32
Computer - > Properties -> Advanced system settings -> Environment Variables -> System Variables -> path, 添加
…\MATLAB\runtime\win32;
…\MATLAB\bin;
…\MATLAB\bin\win32
…\MATLAB\extern\lib\win32\microsoft;

5.VS2013环境配置

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

libeng.liblibmat.liblibmex.liblibmx.libmclmcrrt.libmclmcr.liblibAdd.lib(最后这一个是Add.m生成的)  
6. VS2013下编写MFC程序并测试

#include "stdafx.h"#include "TestMatlab.h"#include "TestMatlabDlg.h"#include "afxdialogex.h"#include <stdio.h>#include <string.h>#include <iostream>#include "mclmcr.h"#include "matrix.h"#include "mclcppclass.h"#include "libAdd.h"using namespace std;#ifdef _DEBUG#define new DEBUG_NEW#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialogEx{public:    CAboutDlg();// 对话框数据    enum { IDD = IDD_ABOUTBOX };    protected:    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现protected:    DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD){}void CAboutDlg::DoDataExchange(CDataExchange* pDX){    CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)END_MESSAGE_MAP()// CTestMatlabDlg 对话框CTestMatlabDlg::CTestMatlabDlg(CWnd* pParent /*=NULL*/)    : CDialogEx(CTestMatlabDlg::IDD, pParent){    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CTestMatlabDlg::DoDataExchange(CDataExchange* pDX){    CDialogEx::DoDataExchange(pDX);    DDX_Control(pDX, IDC_RESULT_EDIT, m_calcResult);}BEGIN_MESSAGE_MAP(CTestMatlabDlg, CDialogEx)    ON_WM_SYSCOMMAND()    ON_WM_PAINT()    ON_WM_QUERYDRAGICON()    ON_BN_CLICKED(IDC_CALCULATE_BUTTON, &CTestMatlabDlg::OnBnClickedCalculateButton)END_MESSAGE_MAP()// CTestMatlabDlg 消息处理程序BOOL CTestMatlabDlg::OnInitDialog(){    CDialogEx::OnInitDialog();    // 将“关于...”菜单项添加到系统菜单中。    // IDM_ABOUTBOX 必须在系统命令范围内。    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);    ASSERT(IDM_ABOUTBOX < 0xF000);    CMenu* pSysMenu = GetSystemMenu(FALSE);    if (pSysMenu != NULL)    {        BOOL bNameValid;        CString strAboutMenu;        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);        ASSERT(bNameValid);        if (!strAboutMenu.IsEmpty())        {            pSysMenu->AppendMenu(MF_SEPARATOR);            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);        }    }    // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动    //  执行此操作    SetIcon(m_hIcon, TRUE);         // 设置大图标    SetIcon(m_hIcon, FALSE);        // 设置小图标    // TODO:  在此添加额外的初始化代码    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE}void CTestMatlabDlg::OnSysCommand(UINT nID, LPARAM lParam){    if ((nID & 0xFFF0) == IDM_ABOUTBOX)    {        CAboutDlg dlgAbout;        dlgAbout.DoModal();    }    else    {        CDialogEx::OnSysCommand(nID, lParam);    }}// 如果向对话框添加最小化按钮,则需要下面的代码//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,//  这将由框架自动完成。void CTestMatlabDlg::OnPaint(){    if (IsIconic())    {        CPaintDC dc(this); // 用于绘制的设备上下文        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);        // 使图标在工作区矩形中居中        int cxIcon = GetSystemMetrics(SM_CXICON);        int cyIcon = GetSystemMetrics(SM_CYICON);        CRect rect;        GetClientRect(&rect);        int x = (rect.Width() - cxIcon + 1) / 2;        int y = (rect.Height() - cyIcon + 1) / 2;        // 绘制图标        dc.DrawIcon(x, y, m_hIcon);    }    else    {        CDialogEx::OnPaint();    }}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSOR CTestMatlabDlg::OnQueryDragIcon(){    return static_cast<HCURSOR>(m_hIcon);}void CTestMatlabDlg::OnBnClickedCalculateButton(){    // TODO:  在此添加控件通知处理程序代码    double a = 6;    double b = 9;    double c;    // initialize lib,这里必须做初始化!    if (!libAddInitialize())    {        MessageBox(_T("Could not initialize libMyAdd!"));           }    // 为变量分配内存空间,可以查帮助mwArray    mwArray mwA(1, 1, mxDOUBLE_CLASS); // 1,1表示矩阵的大小(所有maltab只有一种变量,就是矩阵,为了和Cpp变量接轨,设置成1*1的矩阵,mxDOUBLE_CLASS表示变量的精度)    mwArray mwB(1, 1, mxDOUBLE_CLASS);    mwArray mwC(1, 1, mxDOUBLE_CLASS);    // set data,调用类里面的SetData函数给类赋值    mwA.SetData(&a, 1);    mwB.SetData(&b, 1);    // using my add,掉我自己写的函数    Add(1, mwC, mwA, mwB);    // get data,调用类里面的Get函数获取取函数返回值    c = mwC.Get(1, 1);    CString str;    str.Format(_T("%.5f"), c);    SetDlgItemText(IDC_RESULT_EDIT, str);    // 后面是一些终止调用的程序    // terminate the lib    libAddTerminate();    // terminate MCR    //mclTerminateApplication();}
 将MATLAB编译生成的.h文件添加到头文件里,编译生成解决方案时提示错误:error LNK2019: 无法解析的外部符号 _ref_count_obj_addref,该符号在函数 "protected: __thiscall mwArray::mwArray(class array_ref *,bool)" (??0mwArray@@IAE@PAVarray_ref@@_N@Z) 中被引用 
    1>TestMatlabDlg.obj : error LNK2019: 无法解析的外部符号 _ref_count_obj_addref,该符号在函数 "protected: __thiscall mwArray::mwArray(class array_ref *,bool)" (??0mwArray@@IAE@PAVarray_ref@@_N@Z) 中被引用1>TestMatlabDlg.obj : error LNK2019: 无法解析的外部符号 _array_ref_getV_int,该符号在函数 "public: class mwArray __cdecl mwArray::GetPromoted(unsigned int,...)" (?GetPromoted@mwArray@@QAA?AV1@IZZ) 中被引用1>TestMatlabDlg.obj : error LNK2019: 无法解析的外部符号 _array_ref_get_numeric_mxDouble,该符号在函数 "public: __thiscall mwArray::operator double(void)const " (??BmwArray@@QBENXZ) 中被引用1>TestMatlabDlg.obj : error LNK2019: 无法解析的外部符号 _array_ref_set_numeric_mxDouble,该符号在函数 "public: void __thiscall mwArray::SetData(double *,unsigned int)" (?SetData@mwArray@@QAEXPANI@Z) 中被引用1>TestMatlabDlg.obj : error LNK2019: 无法解析的外部符号 _error_info_get_message,该符号在函数 "public: virtual char const * __thiscall mwException::what(void)const " (?what@mwException@@UBEPBDXZ) 中被引用1>TestMatlabDlg.obj : error LNK2019: 无法解析的外部符号 _mclcppGetLastError,该符号在函数 "public: static void __cdecl mwException::raise_error(void)" (?raise_error@mwException@@SAXXZ) 中被引用1>TestMatlabDlg.obj : error LNK2019: 无法解析的外部符号 _mclcppCreateError,该符号在函数 "public: __thiscall mwException::mwException(class error_info *,bool)" (??0mwException@@QAE@PAVerror_info@@_N@Z) 中被引用1>TestMatlabDlg.obj : error LNK2019: 无法解析的外部符号 _mclGetMatrix,该符号在函数 "public: __thiscall mwArray::mwArray(unsigned int,unsigned int,enum mxClassID,enum mxComplexity)" (??0mwArray@@QAE@IIW4mxClassID@@W4mxComplexity@@@Z) 中被引用1>TestMatlabDlg.obj : error LNK2019: 无法解析的外部符号 _libAddInitialize,该符号在函数 "public: void __thiscall CTestMatlabDlg::OnBnClickedCalculateButton(void)" (?OnBnClickedCalculateButton@CTestMatlabDlg@@QAEXXZ) 中被引用1>TestMatlabDlg.obj : error LNK2019: 无法解析的外部符号 _libAddTerminate,该符号在函数 "public: void __thiscall CTestMatlabDlg::OnBnClickedCalculateButton(void)" (?OnBnClickedCalculateButton@CTestMatlabDlg@@QAEXXZ) 中被引用1>TestMatlabDlg.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) void __cdecl Add(int,class mwArray &,class mwArray const &,class mwArray const &)" (__imp_?Add@@YAXHAAVmwArray@@ABV1@1@Z),该符号在函数 "public: void __thiscall CTestMatlabDlg::OnBnClickedCalculateButton(void)" (?OnBnClickedCalculateButton@CTestMatlabDlg@@QAEXXZ) 中被引用1>D:\A_DATA\Learning_OpenCV\VS_learning_opencv\TestMatlab副本\Debug\TestMatlab.exe : fatal error LNK1120: 12 个无法解析的外部命令
 **解决方案:1.VS2013的编译平台换成X64         2.安装32位MATLAB2014a**

这里写图片描

附:如果有问题请留言描述问题,或留下QQ