Bootstrap

【MPC】④二次规划求解器quadprog的C++动态库接口解析

之前的文章已经介绍:
1、二次规划问题MATLAB求解器quadprog
2、二次规划问题的基本概念
3、二次规划求解器quadprog的win平台下C++动态库生成
本篇文章,主要介绍quadprog动态库的接口与使用

一、matlab函数接口

%没有等式约束的标准二次规划问题
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类接口,共6个函数,分别是一般接口和功能接口。

(一)一般接口

extern LIB_C_QUADPROG_C_API 
bool MW_CALL_CONV C_QUADPROGInitializeWithHandlers(
       mclOutputHandlerFcn error_handler, 
       mclOutputHandlerFcn print_handler);

extern LIB_C_QUADPROG_C_API 
bool MW_CALL_CONV C_QUADPROGInitialize(void);

extern LIB_C_QUADPROG_C_API 
void MW_CALL_CONV C_QUADPROGTerminate(void);

extern LIB_C_QUADPROG_C_API 
void MW_CALL_CONV C_QUADPROGPrintStackTrace(void);

(二)功能接口

function X = C_QUADPROG(H,g,A_cons,b_cons,lb,ub)
//mlx接口
bool MW_CALL_CONV mlxC_QUADPROG(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);
//输入参数nlhs和nrhs分别表示输入参数个数和输出参数个数;指针plhs和prhs分别指向输出矩阵和输入参数矩阵的头指针。
//mlf接口,除了int nargout, mxArray** X外,其他参数与M文件趋同
bool MW_CALL_CONV mlfC_QUADPROG(int nargout, mxArray** X, mxArray* H, mxArray* g, mxArray* A_cons, mxArray* b_cons, mxArray* lb, mxArray* ub);
//int nargout输出参数的个数,mxArray** X输出向量

(三)数据类型

MATLAB外部接口技术:https://www.jianshu.com/p/cbdc290c67f7
mxarray和mwarry数据类型详解:https://blog.csdn.net/u010329292/article/details/75005281
mxarray和mwarry数据类型使用:https://blog.csdn.net/m0_46577050/article/details/121647463
C代码比较详细:https://blog.csdn.net/qq_41990294/article/details/109437031

外部编程语言与Matlab进行交互的时候,有两个常用的数据类型接口:mxArray(C语言)和mwArray(C++语言)。两种数据类型,主要在声明、销毁、变量传递有区别。
①mxArray(C语言)
1)声明

#include "matrix.h"
mxArray *a;

2)销毁

mxDestroyArray a;

3)变量传递

mxArray *dest_ptr =mxCreateDoubleMatrix(rows,cols, mxREAL);
memcpy(dest_ptr,source_ptr,MAX_SIZE);//
//double H[3][3] = { {1,-1,1},{-1,2,-2},{1,-2,4} };
//memcpy(mxGetPr(Input_H), (void*)H, sizeof(H));
//1、mxGetPr:获取mxarray类型,目标矩阵地址
//2、(void*):获取源数据矩阵地址
//3、sizeof:获取源数据矩阵的字节大小

4)变量输出

mlfDisplay_mat(1,&mxB,mxA);
//
double Result = mxGetScalar(mxB);
//mxGetScalar来获取输入变量的数值
printf("%f\n", Result);

②mwArray(C++语言)
1)声明

mwArray a;

2)销毁

mwArray类的析构函数自动销毁对象

3)变量传递

mwArray in1(rows, cols, mxDOUBLE_CLASS, mxREAL); 
mwArray in2(rows, cols, mxDOUBLE_CLASS, mxREAL); 
in1.SetData(data, rows*cols); 
in2.SetData(data, rows*cols);
//例如:
int a[6] = {1,2,3,4,5,6}
mwArray A(2,3,mxINT32_CLASS);  
A.SetData(a,6); //第二个参数为要设置的数的个数,大小可设为rows*cols
//数据类型:
typedef enum
{
    mxUNKNOWN_CLASS = 0, //未知类型
    mxCELL_CLASS, //细胞类型
    mxSTRUCT_CLASS, //结构类型
    mxLOGICAL_CLASS, //布尔类型
    mxCHAR_CLASS,  //字符串类型
    mxVOID_CLASS,  //void类型
    mxDOUBLE_CLASS, 
    mxSINGLE_CLASS, //单精度浮点数
    mxINT8_CLASS, //
    mxUINT8_CLASS,
    mxINT16_CLASS,
    mxUINT16_CLASS,
    mxINT32_CLASS,
    mxUINT32_CLASS,
    mxINT64_CLASS,
    mxUINT64_CLASS,
    mxFUNCTION_CLASS, //函数类型
    mxOPAQUE_CLASS, //
    mxOBJECT_CLASS  //对象类型
}
///
double data[4] = {1.0, 2.0, 3.0, 4.0};
double x;
mwArray a(2, 2, mxDOUBLE_CLASS);
a.SetData(data, 4);
x = (double)a(1,1);
x = (double)a(1,2);
x = (double)a(2,1);
x = (double)a(2,2);

三、C++主程序调用

主函数流程:
初始化应用程序–>初始化动态库–>算法操作—>关闭动态链接库–>关闭应用程序

(一)一般接口使用

①初始化应用程序

//初始化DLL动态连接文件
mclmcrInitialize();
// 鉴定Matlab外部调用环境设置是否正确.
if (!mclInitializeApplication(NULL, 0)) {
	cout << "error1" << endl;
	return -1;
}

②初始化动态链接库

C_QUADPROGInitialize();
if (!C_QUADPROGInitialize()) {
	cout << "error2" << endl;
	return -1;
}

③关闭动态链接库

C_QUADPROGTerminate(); //结束DLL库

④关闭应用程序

mclTerminateApplication();  

(二)功能接口使用

①matlab接口

//matlab函数接口
function X = C_QUADPROG(H,g,A_cons,b_cons,lb,ub)

②mlx接口

//mlx接口
bool MW_CALL_CONV mlxC_QUADPROG(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);
//输入参数nlhs和nrhs分别表示输入参数个数和输出参数个数;指针plhs和prhs分别指向输出矩阵和输入参数矩阵的头指针。
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];

③mlf接口

//mlf接口,除了int nargout, mxArray** X外,其他参数与M文件趋同
bool MW_CALL_CONV mlfC_QUADPROG(int nargout, mxArray** X, mxArray* H, mxArray* g, mxArray* A_cons, mxArray* b_cons, mxArray* lb, mxArray* ub);
//int nargout输出参数的个数,mxArray** X输出向量
//参考:
#include <stdio.h>
#include <math.h>
#include "libPkg.h" //编译建立的库头文件
main( int argc, char **argv )
{
    mxArray *N;        /* 输入变量矩阵指针 */
    mxArray *R = NULL; /* 结果矩阵指针 */
    int  n; //默认的M文件输入变量数值
    /* 获取命令行参数,如果命令行输入小于2,则输入参数默认为5 */
    if (argc >= 2) {
        n = atoi(argv[1]);
    } else {
        n = 5;
    }
    //初始化MCR和libPkg函数库
    mclInitializeApplication(NULL,0);
    libPkgInitialize(); 
    /* 得到输入参量的数值 */
    N = mxCreateDoubleScalar(n); 
    /*调用magicCreat.m编译后的文件mlfMagicCreat*/
    mlfMagicCreat(1, &R, N);  
    /* 释放内存空间*/
    mxDestroyArray(N);
    mxDestroyArray(R);
    //结束libPkg库和MCR
    libPkgTerminate(); 
    mclTerminateApplication();
}
;