一、将Matlab的quadprog函数转为VS可调用的lib及dll链接库
参考文章:VS2008 与 Matlab 的混合编程(quadprog函数为例)_jiabingxi的博客-CSDN博客
主要步骤为:
1.在Matlab中写一个脚本.m文件(这里命名为C_QUADPROG.m)
function X = C_QUADPROG(H,g,A_cons,b_cons,lb,ub)
%C_QUADPROG 输入六个参数,假设没有等式约束,即Aeq = [] 和 beq = []
X = quadprog(H,g,A_cons,b_cons,[],[],lb,ub);
end
2.在命令行窗口输入
>>mbuild -setup
选择“mex -setup C++ -client MBUILD ”后,再在命令行窗口输入>>deploytool,选择Library Compiler,用以生成lib链接库。
在Library Compiler工具箱生成C++链接库:
点击“Package”直接生成链接库。
3.将生成的链接库文件导入C++工程:
打开VS2019新建一个工程,然后将C_QUADPROG.dll,C_QUADPROG.lib,C_QUADPROG.ctf,C_QUADPROG.h四个文件复制到工程目录下。选择“工具-选项-项目和解决方案-VC++目录”,在“显示以下内容目录”里选择“包含文件”将“F:\MATLAB2022a\extern\include”添加进去,然后选择“库文件”将“F:\MATLAB2022a\extern\lib\win32\microsoft”添加进去,大家可根据自己Matlab实际安装的路径进行修改。
然后选择“项目-属性-配置属性-链接器-输入”,在右边“附加依赖项”一栏填入“C_QUADPROG.lib” 和“mclmcrrt.lib”,其中C_QUADPROG.lib是刚刚用Matlab生成的lib文件,mclmcrrt是调用MATLAB引擎的一个lib文件。
4.将所生成的函数的头文件.h及静态链接库.lib分别部署在头文件与资源文件中:
(①mclmcrrt.lib位于“F:\MATLAB2022a\extern\lib\win64\microsoft”
②调式工程时遇到问题:报错:”Cstring”:未声明的标识符时,查阅资料发现原因:
CString是MFC中最常见的类之一,用于封装字符串数据结构,需要引入MFC的头文件:
解决:在main.cpp最上方添加 #include "stdafx.h" 的头文件声明,相应地,在解决方案栏加入stdafx.h的文件)
5.编写调试的main.cpp:
在源文件“添加”-->“新建项”,选择C++文件,并命名为main.cpp
代码如下:
#pragma comment(lib, "C_QUADPROG.lib") //与在属性配置中“添加附加依赖项”的作用相同,前三行可以省去
#pragma comment(lib, "mclmcr.lib")
#pragma comment(lib, "mclmcrrt.lib")
#include <iostream>
#include "stdafx.h"
#include "C_QUADPROG.h"
using namespace std;
int main()
{
printf("进入main函数");
//初始化DLL动态连接文件
mclmcrInitialize();
// 鉴定Matlab外部调用环境设置是否正确.
if (!mclInitializeApplication(NULL, 0)) {
cout << "error1" << endl;
return -1;
}
C_QUADPROGInitialize();
if (!C_QUADPROGInitialize()) {
cout << "error2" << endl;
return -1;
}
//输入矩阵、数组
double H[3][3] = { {1,-1,1},{-1,2,-2},{1,-2,4} };
double g[3][1] = { {-7},{-12},{-15} };
double A[1][3] = {1, 1, 1};
double b[1] = {1};
double lb[3][1] = { {-10},{-10},{-10} };
double ub[3][1] = { {10},{10},{10} };
//输出矩阵、数组
//double x_out[2];
//double fval_out[1];
//为QUADASSINPROG函数创建输入参数矩阵
mxArray* Input_H = mxCreateDoubleMatrix(3, 3, mxREAL);
//将输入矩阵、数组拷贝至QUADASSINPROG输入参数
memcpy(mxGetPr(Input_H), (void*)H, sizeof(H));
mxArray* Input_g = mxCreateDoubleMatrix(3, 1, mxREAL);
memcpy(mxGetPr(Input_g), (void*)g, sizeof(g));
mxArray* Input_A = mxCreateDoubleMatrix(1, 3, mxREAL);
memcpy(mxGetPr(Input_A), (void*)A, sizeof(A));
mxArray* Input_b = mxCreateDoubleMatrix(1, 1, mxREAL);
memcpy(mxGetPr(Input_b), (void*)b, sizeof(b));
mxArray* Input_lb = mxCreateDoubleMatrix(3, 1, mxREAL);
memcpy(mxGetPr(Input_lb), (void*)lb, sizeof(lb));
mxArray* Input_ub = mxCreateDoubleMatrix(3, 1, mxREAL);
memcpy(mxGetPr(Input_ub), (void*)ub, sizeof(ub));
mxArray* Input[6] = { Input_H, Input_g, Input_A, Input_b, Input_lb, Input_ub };
mxArray* Output[2];
//调用Matlab中的函数 function [x, fval] = QUADASSINPROG(H, C, A, b, lb)以测试
mlxC_QUADPROG( 1, Output, 6, Input);
//为QUADASSINPROG函数创建输出参数指针
mxArray* x = mxCreateDoubleMatrix(1, 3, mxREAL); //输出的x的大小也要随输入矩阵的大小更改
//mxArray* fval = mxCreateDoubleMatrix(1, 1, mxREAL);
//将输出参数传递给输出参数指针
x = Output[0];
//fval = Output[1];
double *x_out = mxGetPr(x); //x_out是DLL开始前定义的double数组;x是DLL开始后定义的mxArray数组
//double *fval_out = mxGetPr(fval);
memcpy(x, mxGetPr(x), sizeof(x));
//memcpy(fval, mxGetPr(fval), sizeof(fval));
CString resultStr;
resultStr.Format("控制量结果:% f % f % f ", x_out[0], x_out[1], x_out[2]);
cout << resultStr << endl;
cout << "结束" << endl;
//char anyKey;
//cin >> anyKey;
C_QUADPROGTerminate(); //结束DLL库
system("pause");
return 0;
}
得到的结果:
二、工程配置时遇到的问题及解决
1.遇到:error LNK2019:无法解析的外部符号... 该符号在函数 _main 中被引用
原因可能是编译的平台不对,由于目前多数Matlab是基于64位计算机平台,故其生成的函数也适用于64位平台
2.遇到错误:“cout”未声明的标识符
①在声明头文件时加入#include <iostream>的标准输入输出流
②在开头添加引号内的内容“using namespace std;"
3.出现了大量类似“error LNK1104:无法打开文件***.lib”这样的错误,网上说需要添加链接库,添加相应的lib库(在VS的安装路径、MATLAB的安装路径、“C:\Program Files (x86)\Microsoft Visual Studio\Microsoft Visual Studio\VC98\Lib”、“C:VProgram Files (x86)Windows Kits\10\Lib\10.0.19041.0\um\x64”等很多路径添加到“项目属性-->C/C++ --> 附加库目录”)后还是不行,甚至出现“ 缺少“;”,错误计数超过 100;正在停止编译”,原因是在附加库目录里面添加太多的lib路径,在相互调用时出现重复引用、顺序不对等叠加乱码的现象。
解决:
最后发现在设置包含目录、库目录、附加包含目录等时没有勾选继承选项,勾选上“从父项或项目默认设置继承”就没问题了。