在进行实际项目时,有时候需要使用别人封装好的dll,或者自己编写的封装好的dll,本文从实际使用的角度出发,在VS环境下,使用c++语言编写了同时调用三个dll的调用函数以及其dll的生成函数。
一、firstDll
该dll封装了一个简单加法函数,配合使用静态调用的方法,如下为代码部分
1、使用VS创建一个空项目,在空项目下创建一个cpp文件和一个h头文件
2、cpp文件写加法函数的函数体,并且引用h头文件
#include"firstDll.h"
int __stdcall add(int a, int b)
{
return a + b;
}
3、h文件写一个接口,内部声明一些结构体定义以及函数
#pragma once
#ifdef __cplusplus // 一般用于将C++代码以标准C形式输出(即以C的形式被调用)
extern"C" { // 告诉编译器下面大括号括起来的函数是c语言函数(因为c++和c语言对函数的编译转换不一样,主要是c++中存在重载)
#endif
__declspec(dllexport) int __stdcall add(int a, int b); // __declspec(dllexport)声明导出该函数供外部调用
// __stdcall是Windows API默认的函数调用协议,函数采用从右到左的压栈方式,自己在退出时清空堆栈,也可以不使用
#ifdef __cplusplus
}
#endif
4、修改属性中的输出,将exe改为动态库dll
5、生成解决方案后,即可找到dll、exp、lib、pdb四个类型的文件
此时便完成了dll的制作
二、secondDll
该dll封装了一个简单的调用scip求解混合整数规划问题的方法,配合使用静态调用的方法,如下为代码部分
1、需要按要求配置scip求解器
2、cpp文件写加法函数的函数体,并且引用h头文件
#include <iostream>
#include"secondDll.h"
#include <scip/scipdefplugins.h>
#pragma comment(lib,"libscip.lib")
res _stdcall mipTest()
{
res ret;
// creates and initializes SCIP data structures
SCIP* _scip;
SCIPcreate(&_scip);
// include default plugins
SCIPincludeDefaultPlugins(_scip);
// creates empty problem and initializes all solving data structures
SCIPcreateProbBasic(_scip, "test");
//sets objective sense of problem
SCIPsetObjsense(_scip, SCIP_OBJSENSE_MINIMIZE);
// changes the value of an existing SCIP_Real parameter
SCIPsetRealParam(_scip, "limits/gap", 0.00001);
SCIPsetRealParam(_scip, "limits/time", 10);
//--添加变量
SCIP_VAR* xVar = nullptr;
SCIPcreateVarBasic(_scip, &xVar, "_x", 0, SCIPinfinity(_scip), 2.0, SCIP_VARTYPE_INTEGER);
SCIPaddVar(_scip, xVar);
SCIP_VAR* yVar = nullptr;
SCIPcreateVarBasic(_scip, &yVar, "_y", 0, SCIPinfinity(_scip), 3.0, SCIP_VARTYPE_INTEGER);
SCIPaddVar(_scip, yVar);
//--添加约束
SCIP_CONS* zCons;
SCIPcreateConsBasicLinear(_scip, &zCons, "z_cons", 0, NULL, NULL, 7, SCIPinfinity(_scip));
SCIPaddCoefLinear(_scip, zCons, xVar, 2);
SCIPaddCoefLinear(_scip, zCons, yVar, 3);
SCIPaddCons(_scip, zCons);
SCIPsolve(_scip);
//--取最优解
SCIP_Real x_value = SCIPgetSolVal(_scip, SCIPgetBestSol(_scip), xVar);
SCIP_Real y_value = SCIPgetSolVal(_scip, SCIPgetBestSol(_scip), yVar);
//--释放资源
SCIPreleaseVar(_scip, &xVar);
SCIPreleaseVar(_scip, &yVar);
SCIPreleaseCons(_scip, &zCons);
SCIPfree(&_scip);
std::cout << "x_value: " << x_value << std::endl;
std::cout << "y_value: " << y_value << std::endl;
ret.x = x_value;
ret.y = y_value;
return ret;
}
3、h文件写一个接口,内部声明一些结构体定义以及函数
#pragma once
struct res
{
int x;
int y;
};
extern "C" _declspec(dllexport) res _stdcall mipTest();
4、按照上面的方法生成四个文件
三、thirdDll
该dll封装了一个简单的减法函数,配合使用动态调用的方法,如下为代码部分
1、cpp部分
#pragma once
#include"thirdDll.h"
int __stdcall subec(int a, int b)
{
return a - b;
}
2、h部分
#pragma once
#ifdef __cplusplus // 一般用于将C++代码以标准C形式输出(即以C的形式被调用)
extern"C" { // 告诉编译器下面大括号括起来的函数是c语言函数(因为c++和c语言对函数的编译转换不一样,主要是c++中存在重载)
#endif
__declspec(dllexport) int __stdcall subec(int a, int b); // __declspec(dllexport)声明导出该函数供外部调用
// __stdcall是Windows API默认的函数调用协议,函数采用从右到左的压栈方式,自己在退出时清空堆栈,也可以不使用
#ifdef __cplusplus
}
#endif
3、编译生成四个文件
四、本章节介绍如何调用上面生成的四个dll方法
1、创建一个空项目,写好主函数并运行一次(目的是生成exe的根目录)
2、将以上生成的dll放到exe目录下,将lib放到函数体目录下
3、每个dll都有一个h文件,内容与dll中的类似,目的是声明dll中输入输出的类与结构体、函数等
4、h文件
firstDll.h
#pragma once
//本dll为一个简单的加法函数
// 这里使用__declspec(dllimport),正好和生成dll时的__declspec(dllexport)对应
// 生成dll时没有加__stdcall的话,这里也不用加
#pragma comment(lib, "firstDll.lib") // 告诉程序lib文件的路径,这里就表示当前目录
extern "C" __declspec(dllimport) int __stdcall add(int a, int b);
secondDll.h
#pragma once
//本dll为一个scip编写简单线性规划的DLL
// 这里使用__declspec(dllimport),正好和生成dll时的__declspec(dllexport)对应
// 生成dll时没有加__stdcall的话,这里也不用加
#pragma comment(lib, "secondDll.lib") // 告诉程序lib文件的路径,这里就表示当前目录
struct res
{
int x;
int y;
};
extern "C" __declspec(dllimport) res __stdcall mipTest();
secondDll使用动态调用,因此可以不需要头文件,但是结构体之类如果存在还是需要
5、cpp
#include <iostream>
#include"firstDll.h"
#include"second.h"
#include<windows.h>
using namespace std;
int main()
{
cout << "====================================firstDll调用 加法函数 使用静态调用===========================================" << endl;
int a = 3;
int b = 2;
std::cout << "add result is: " << add(a, b) << std::endl;
cout << "=====================================secondDll调用 scip求简单线性规划 使用静态调用================================" << endl;
std::cout << "mip x result is: " << mipTest().x << " ,mip y result is: " << mipTest().y << std::endl;
cout << "====================================firstDll调用 减法函数 使用动态调用===========================================" << endl;
// 动态调用DLL库
// 运行时加载DLL库
HMODULE module = LoadLibraryA("thirdDll.dll"); // 根据DLL文件名,加载DLL,返回一个模块句柄
if (module == NULL)
{
printf("加载thirdDll.dll动态库失败\n");
}
typedef int(*subFunc)(int, int); // 定义函数指针类型
subFunc sub;
// 导出函数地址
sub = (subFunc)GetProcAddress(module, "subec"); // GetProcAddress返回指向的函数名的函数地址
int sum = sub(100, 200);
printf("动态调用,subec = %d\n", sum);
system("pause");
return 0;
}
6、运行结果
====================================firstDll调用 加法函数 使用静态调用===========================================
add result is: 5
=====================================secondDll调用 scip求简单线性规划 使用静态调用================================
feasible solution found by trivial heuristic after 0.0 seconds, objective value 5.000000e+05
presolving:
(round 1, fast) 0 del vars, 0 del conss, 0 add conss, 4 chg bounds, 0 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs
(0.0s) running MILP presolver
(0.0s) MILP presolver found nothing
(round 2, exhaustive) 0 del vars, 0 del conss, 0 add conss, 4 chg bounds, 0 chg sides, 0 chg coeffs, 1 upgd conss, 0 impls, 0 clqs
(0.0s) symmetry computation started: requiring (bin +, int +, cont +), (fixed: bin -, int -, cont -)
(0.0s) no symmetry present (symcode time: 0.00)
presolving (3 rounds: 3 fast, 2 medium, 2 exhaustive):
0 deleted vars, 0 deleted constraints, 0 added constraints, 4 tightened bounds, 0 added holes, 0 changed sides, 0 changed coefficients
0 implications, 0 cliques
presolved problem has 2 variables (0 bin, 2 int, 0 impl, 0 cont) and 1 constraints
1 constraints of type <varbound>
transformed objective value is always integral (scale: 1)
Presolving Time: 0.00
time | node | left |LP iter|LP it/n|mem/heur|mdpt |vars |cons |rows |cuts |sepa|confs|strbr| dualbound | primalbound | gap | compl.
t 0.0s| 1 | 0 | 0 | - | trivial| 0 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 7.000000e+00 | 1.700000e+01 | 142.86%| unknown
p 0.0s| 1 | 0 | 0 | - | vbounds| 0 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 7.000000e+00 | 9.000000e+00 | 28.57%| unknown
p 0.0s| 1 | 0 | 0 | - | vbounds| 0 | 2 | 1 | 0 | 0 | 0 | 1 | 0 | 7.000000e+00 | 8.000000e+00 | 14.29%| unknown
* 0.0s| 1 | 0 | 0 | - | LP | 0 | 2 | 0 | 0 | 0 | 0 | 2 | 0 | 7.000000e+00 | 7.000000e+00 | 0.00%| unknown
0.0s| 1 | 0 | 0 | - | 583k | 0 | 2 | 0 | 0 | 0 | 0 | 2 | 0 | 7.000000e+00 | 7.000000e+00 | 0.00%| unknown
SCIP Status : problem is solved [optimal solution found]
Solving Time (sec) : 0.00
Solving Nodes : 1
Primal Bound : +7.00000000000000e+00 (5 solutions)
Dual Bound : +7.00000000000000e+00
Gap : 0.00 %
x_value: 2
y_value: 1
feasible solution found by trivial heuristic after 0.0 seconds, objective value 5.000000e+05
presolving:
(round 1, fast) 0 del vars, 0 del conss, 0 add conss, 4 chg bounds, 0 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs
(0.0s) running MILP presolver
(0.0s) MILP presolver found nothing
(round 2, exhaustive) 0 del vars, 0 del conss, 0 add conss, 4 chg bounds, 0 chg sides, 0 chg coeffs, 1 upgd conss, 0 impls, 0 clqs
(0.0s) symmetry computation started: requiring (bin +, int +, cont +), (fixed: bin -, int -, cont -)
(0.0s) no symmetry present (symcode time: 0.00)
presolving (3 rounds: 3 fast, 2 medium, 2 exhaustive):
0 deleted vars, 0 deleted constraints, 0 added constraints, 4 tightened bounds, 0 added holes, 0 changed sides, 0 changed coefficients
0 implications, 0 cliques
presolved problem has 2 variables (0 bin, 2 int, 0 impl, 0 cont) and 1 constraints
1 constraints of type <varbound>
transformed objective value is always integral (scale: 1)
Presolving Time: 0.00
time | node | left |LP iter|LP it/n|mem/heur|mdpt |vars |cons |rows |cuts |sepa|confs|strbr| dualbound | primalbound | gap | compl.
t 0.0s| 1 | 0 | 0 | - | trivial| 0 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 7.000000e+00 | 1.700000e+01 | 142.86%| unknown
p 0.0s| 1 | 0 | 0 | - | vbounds| 0 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 7.000000e+00 | 9.000000e+00 | 28.57%| unknown
p 0.0s| 1 | 0 | 0 | - | vbounds| 0 | 2 | 1 | 0 | 0 | 0 | 1 | 0 | 7.000000e+00 | 8.000000e+00 | 14.29%| unknown
* 0.0s| 1 | 0 | 0 | - | LP | 0 | 2 | 0 | 0 | 0 | 0 | 2 | 0 | 7.000000e+00 | 7.000000e+00 | 0.00%| unknown
0.0s| 1 | 0 | 0 | - | 583k | 0 | 2 | 0 | 0 | 0 | 0 | 2 | 0 | 7.000000e+00 | 7.000000e+00 | 0.00%| unknown
SCIP Status : problem is solved [optimal solution found]
Solving Time (sec) : 0.00
Solving Nodes : 1
Primal Bound : +7.00000000000000e+00 (5 solutions)
Dual Bound : +7.00000000000000e+00
Gap : 0.00 %
x_value: 2
y_value: 1
mip x result is: 2 ,mip y result is: 1
====================================firstDll调用 减法函数 使用动态调用===========================================
动态调用,subec = -100
请按任意键继续. . .