脚本宝典收集整理的这篇文章主要介绍了DLL入门指南,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
了解DLL
什么是dll文件
dll 的全称叫:动态链接库程序,是为可执行文件服务的,每个 dll 中有诸多的函数供可执行文件主体调用!
在Linux下的表现形式为 .so 文件。dll 文件与 .exe 可执行文件同属于 PE 文件类型,与 .exe 文件不同的是:dll文件需要有重定位表以及导出表
而 .exe 文件不一定需要。与 dll 对应的是静态链接库,通常是 .a 文件
为什么需要dll
- 在 Windows 中,每个程序都可以使用某个 dll 中的函数,这有助于促进代码重用和内存的有效使用
- 通过使用 dll,程序可以实现模块化
- 只在需要某个模块的功能时才导入该模块,便于主程序的快速加载
- 可以非常容易地将更新应用于各个模块,而不会影响该程序的其他部分
怎么链接dll
- 动态链接库的显式链接,使用
LoadLibrary()、GetPRoCADdress()和FreeLibrary()
函数
- 动态链接库的隐式链接,在代码中添加
#include "..MyLibMyLib.h" 以及 #pragma comment(lib,"MyLib.lib")
,并把相应的 dll 文件放在代码的目录下
编写DLL
编写前的准备
dll 的编写特别要注意你的编译器选择,我目前也只用了两个主流的编译器做过测试,一个是微软 VisualStudio 自带的 MSVC编译器
,另一个是 GNU 在 Windows 上的 MinGW编译器
如果你使用 MinGW,那么和写普通程序区别不大;但如果你使用 MSVC 的话,你就需要注意一些固定的格式,以及一些宏定义
MSVC版
直接新建一个 dll 文件项目,先写一个头文件,把一些变量和函数的定义写好,这里有兴趣的话可以了解一下 #ifdef
以及 extern "C" __declspec(dllimport)
,头文件 header.h 代码如下
#ifdef MYLIBAPI
#define MYLIBAPI extern "C" __declspec(dllexport)
#else
#define MYLIBAPI extern "C" __declspec(dllimport)
#endif
MYLIBAPI int res;
MYLIBAPI int myadd(int num1,int num2);
然后是主要的功能代码,mydll.c 代码如下
#include <windows.h>
#define MYLIBAPI extern "C" __declspec(dllimport)
#include "header.h"
int res;
int myadd(int num1,int num2){
res = num1 + num2;
return res;
}
注意事项:
extern "C"
主要是排除 C++ 编译的干扰,C++ 编译某个函数后会变成 func@ 的形式,不方便主程序根据函数名调用
__declspec(dllimport)
从其它动态库中声明导入函数、类、对象等供本动态库或exe文件使用,在没有全局静态变量时可以不使用该关键字
__declspec(dllexport)
声明为导出函数、类、对象等供其它程序调用,如果不使用该关键字导出 dll 函数,则需要 .def 文件
MinGW版
使用 MinGW 编译器的话和写普通程序类似,只写需要用到的函数即可,不需要 main 主函数,然后编译成 dll 文件即可。编译一句搞定 gcc math.c -shared -o math.dll -Wl,--out-implib,math.lib,--output-def,math.def
,还能生成 .lib 以及 .def 文件,用 C++ 的话可能还需要 --kill-at
,mydll.c 代码如下:
#include<stdio.h>
int add(int a,int b){
return a+b;
}
int sub(int a,int b){
return a-b;
}
int mul(int a,int b){
return a*b;
}
int div(int a,int b){
return a/b;
}
// gcc math.c -shared -o math.dll -Wl,--out-implib,math.lib,--output-def,math.def
注意:
dll 程序其实也是有入口函数的-DllMain,操作系统在调用 LoadLibrary() 线程的上下文中调用此入口函数,并且入口函数中通常会说明该 dll 被调用的方式!除非有特殊需求,一般不需要写 DllMain 函数
调用DLL
显式链接调用
调用之前 MSVC 生成的 mydll_vc.dll 中的函数
#include <stdio.h>
#include <windows.h>
int main(){
HINSTANCE hMyDLL = NULL; // typedef HINSTANCE HMODULE;
int (*MyAdd)(int,int);
hMyDLL = LoadLibrary("mydll_vc.dll");
if(hMyDLL == NULL){
printf("Can not open this file!n");
}
MyAdd = (int (*)(int,int))GetProcAddress(hMyDLL,"myadd");
printf("%dn",MyAdd(99,999));
return 0;
}
调用之前 MinGW 生成的 mydll_gcc.dll 中的函数
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
typedef int (*AddFunc)(int,int);
typedef int (*SubFunc)(int,int);
typedef int (*MulFunc)(int,int);
typedef int (*DivFunc)(int,int);
int main(){
int a=66,b=6;
HMODULE hDLL = LoadLibrary("mydll_gcc.dll");
if(hDLL != NULL){
AddFunc add = (AddFunc)GetProcAddress(hDLL, "add");
SubFunc sub = (SubFunc)GetProcAddress(hDLL, "sub");
MulFunc mul = (MulFunc)GetProcAddress(hDLL, "mul");
DivFunc div = (DivFunc)GetProcAddress(hDLL, "div");
if(add != NULL){
printf("a+b=%dn",add(a,b));
}
if(sub != NULL){
printf("a-b=%dn",sub(a,b));
}
if(mul != NULL){
printf("a*b=%dn",mul(a,b));
}
if(div != NULL){
printf("a/b=%dn",div(a,b));
}
}else{
printf("Load Failed!n");
}
FreeLibrary(hDLL);
system("pause");
return 0;
}
隐式链接调用
在代码中添加 #include "..MyLibMyLib.h" 以及 #pragma comment(lib,"MyLib.lib")
,并把相应的 dll 文件放在代码的目录下,然后直接使用函数即可!
END
以上是脚本宝典为你收集整理的DLL入门指南全部内容,希望文章能够帮你解决DLL入门指南所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。