使用环境VS2019
1、生成dll
创建工程时选择dll,工程命名testDll1会生成如下代码,作为dll文件被调用的入口
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
添加如下内容导出函数,使函数可以被其他程序调用,__declspec(dllexport)相关信息直接搜索即可
extern "C" __declspec(dllexport) void test_fun();
/*test_fun();函数被导出,可被其他程序调用*/
void test_fun()
{
MessageBoxA(NULL,"DLL文件测试函数","提示",0);
}
然后生成,会产生如下文件(testDll1是工程名)
testDll1.dll
testDll1.exp
testDll1.lib
testDll1.ilk
2、动态链接库的静态调用(dll和lib文件)。
静态调用是在编译时连接的,动态调用是在运行时使用的。
新建应用工程,将之前生成的testDll1.dll、testDll1.lib复制到新工程的源码目录编译时使用lib文件,运行时使用dll文件。编辑源码如下
#include<Windows.h>
#pragma comment(lib,"testDll1"); //引用库文件
extern "C" void test_fun(); //声明函数
int main()
{
test_fun();
return 0;
}
运行结果:
3、动态链接库的动态调用dll
使用loadlibarty导入dll,再使用GetProcAddress获取指向dll中的函数的地址,即可进行调用。示例如下
LoadLibrary用法:loadlibarty将指定的模块加载到调用进程的地址空间中。指定的模块可能会导致其他模块被加载。形参就是dll的文件名。
如果函数成功,则返回值是模块的句柄。
如果函数失败,则返回值为NULL。
GetProcAddress用法:
FARPROC GetProcAddress( HMODULE hModule, LPCSTR lpProcName );
hModule:包含函数或变量的DLL模块的句柄。
lpProcName :函数名;
如果函数成功,则返回值是导出的函数或变量的地址。
如果函数失败,则返回值为NULL。
#include<Windows.h>
#include <stdio.h>
typedef void (*func_p)(void);
int main()
{
HMODULE handle_dll = NULL;
handle_dll = LoadLibrary(L"testDll1.dll"); //加载动态库(加L是因为编码问题)
if (handle_dll == NULL)
printf("load dll fail\n");
else
{
printf("load dll OK!\n");
func_p f;
f = (func_p)GetProcAddress(handle_dll, "test_fun");
f();
}
return 0;
}
运行结果符合预期。