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

时间:2022-09-22 09:15:56

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编译器

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

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

MATLAB与C++/MFC混合编程;调用MATLAB函数
然后继续在命令行中输入: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编译器。重启后继续输入上面的命令,等待编译完成。

MATLAB与C++/MFC混合编程;调用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环境配置

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

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

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

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

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

libeng.lib
libmat.lib
libmex.lib
libmx.lib
mclmcrrt.lib
mclmcr.lib
libAdd.lib(最后这一个是Add.m生成的)  
6. VS2013下编写MFC程序并测试

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


#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**

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

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