详解dll的封装,以及三种调用方法(将+

您所在的位置:网站首页 外部函数与内部函数的调用方法有哪些 详解dll的封装,以及三种调用方法(将+

详解dll的封装,以及三种调用方法(将+

2024-07-13 23:55| 来源: 网络整理| 查看: 265

2019.8.15再次编辑,看过《深入理解计算机系统》(吐槽:改名“全面”更好)之后,再回来看这些会豁然开朗,「编译 --> 链接」的过程平时很少关注(因为用不到,而且涉及很多底层知识、设置、api、编码等乱七八糟不得不用却只用一次的玩意儿),甚至有时别人给的dll配置不上还会让人恼火——其实把程序设计成可链接是为了降低耦合性,而且减少不必要的其他模块的编译工作,便于分工,让每个人的模块各司其职,实际上是很有用的!!!

一、生成DLL 1.新建dll项目

新建 “Visual C++”-“Windows桌面”-“动态链接库(DLL)” 

或者:

新建 “Visual C++”-“Win32”-“Win32 控制台应用程序” 

再右键 自己的项目:属性,然后在 常规->配置类型 改为动态库(.dll)

比如我建了一个叫“dllmain”的工程。

 

2.怎么去写代码

 

举个简单例子,做一个能加减乘除+-*/的dll接口:

创建DLL文件目录下现在用得到的有:dllmain.h 以及dllmain.cpp

(新建项目的其他自动生成的文件不要动,不然无法成功生成dll……)

 

在“dllmain.cpp”文件里添加实现功能的代码(加减乘除):

#include "dllmain.h" #include //标准的异常类,除数为0时使用 double Add(double a, double b) { return a + b;} double Subtract(double a, double b) { return a - b;} double Multiply(double a, double b) { return a * b;} double Divide(double a, double b) { if (b == 0) throw std::invalid_argument("除数不能是 0!"); return a / b; }

 

然后在“dllmain.h”头文件里添加函数声明代码:

这是我们平时的函数声明:

double Add(double a, double b); double Subtract(double a, double b); double Multiply(double a, double b); double Divide(double a, double b);

在dll里为了能被使用,前面添加:extern "C" __declspec(dllexport) 

extern "C" __declspec(dllexport) double Add(double a, double b); extern "C" __declspec(dllexport) double Subtract(double a, double b); extern "C" __declspec(dllexport) double Multiply(double a, double b); extern "C" __declspec(dllexport) double Divide(double a, double b);

为了高逼格一点,可以使用宏定义(把冗长的"__declspec(dllexport)"换成意思清楚的词)

#define MathFuncDll_API __declspec(dllexport) extern "C" MathFuncDll_API double Add(double a, double b); extern "C" MathFuncDll_API double Subtract(double a, double b); extern "C" MathFuncDll_API double Multiply(double a, double b); extern "C" MathFuncDll_API double Divide(double a, double b);

_declspec(dllexport) 意为指定需要导出的目标(生成dll用的)

extern "C",意为将C语言下的程序导出为DLL(这么做的目的见文末”被其他语言调用注意事项“,一句话就是防止在c++编译后函数入口名与c编译后的不一致导致程序找不到函数报错)

 

在.cpp和.h里添加过代码后,”Ctrl+Shift+B“ 或者 ”生成解决方案“都可以,

生成成功,然后DeBug目录下找到 那个生成的 “dllmain.dll”

 

二、调用(链接)

网上搜了一下,这方面还真是有大不相同的好几种方法。。

动态链接库(Dynamic Link Library)DLL文件与EXE文件一样也是可执行文件,但是DLL也被称之为库,因为里面封装了各种类啊,函数啊之类的东西,就像是一个库一样,存储着很多东西,主要是用来调用的。调用方式主要分为两种:隐式(通过lib文件与头文件) 与 显式(只通过DLL文件)【显式调用又分为:静态(需要lib)、动态】。 摘自:https://blog.csdn.net/qq_34097715/article/details/79540933 

 

方法一:隐式调用(项目设置中调用)

编译程序时需要头文件、lib文件,运行时需要DLL文件,并且运行过程中DLL文件一直被占用。但是可以像正常使用一样直接用,而不用调用API!

这个时候我们需要三个文件,头文件(.h)、导入库文件(.lib)、动态链接库(.dll)把生成的.dll和.lib两个文件拷入控制台程序(exe)的Debug文件夹下

添加dll、lib、h三者的引用:

DLL 引用方式

右键项目——属性——链接器——常规——附加库目录——添加.dll所在目录【选择你dllmain.dll所在文件夹】

LIB 引用方式

方法1

右键项目——属性——配置属性——VC++目录——库目录:添加.lib所在的文件夹(确认对应libpath的文件夹)

右键项目——属性——链接器——输入——附加依赖项——添加.lib【输入dllmain.lib】

方法2

由于有些大工程引用较多,也可以 仅仅右键项目,添加,现有项,把.lib先引用进来。否则会报错“无法打开xxxx.lib”!   

H 引用方式

右键项目——属性——配置属性——VC++目录——包含目录:添加.h所在的文件夹(确认对应需要include的文件夹)

在代码里输入#include"dllmain.h"(见有篇博客说要把extern "C" __declspec(dllexport)前缀删掉 ,因为那是生成dll用的)——添加.h

#include #include"dllmain.h" //这里引用 using namespace std; int main() { //隐式加载 dll以及lib,h cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3