1 动态库与静态库区别
静态库
当程序与静态库连接时,库中目标文件所含的所有将被程序使用的函数的机器码被 copy 到最终的可执行文件中。这就会导致最终生成的可执行代码量相对变多,相当于编译器将代码补充完整了,优点,这样运行起来相对就快些。不过会有个缺点: 占用磁盘和内存空间. 静态库会被添加到和它连接的每个程序中, 而且这些程序运行时, 都会被加载到内存中. 无形中又多消耗了更多的内存空间。
动态库
与共享库连接的可执行文件只包含它需要的函数的引用表,而不是所有的函数代码,只有在程序执行时, 那些需要的函数代码才被拷贝到内存中。优点,这样就使可执行文件比较小, 节省磁盘空间,更进一步,操作系统使用虚拟内存,使得一份共享库驻留在内存中被多个程序使用,也同时节约了内存。缺点,不过由于运行时要去链接库会花费一定的时间,执行速度相对会慢一些,总的来说静态库是牺牲了空间效率,换取了时间效率,共享库是牺牲了时间效率换取了空间效率
下面用两个接口分别实现动态库的调用及回调
- dll实现加法运行,应用程序调用dll,将加法结果计算出;
- dll实现加法运行,应用程序调用dll,将加法结果计算出;并且将计算过程通过回调返回给应用程序(实际应用中是比加法更加复杂,这里只是)
2 创建动态库,dll中定义和实现接口
DllAPI.h
#ifndef __DLLAPI_DEF__ #define __DLLAPI_DEF__ typedef void (CALLBACK* CallBackFun)(bool bRet); extern "C" int _declspec(dllexport) add(int x, int y); extern "C" int _declspec(dllexport) addEx(int x, int y, CallBackFun fun); #endif
DllAPI.cpp
#include "stdafx.h"
#include "DllAPI.h"
int add(int x, int y)
{
return x + y;
}
int addEx(int x, int y, CallBackFun fun)
{
int a = x + y;
//处理流程...
//处理完成,返回状态传给应用程序
bool bRet = true;
fun(bRet);
return a;
}
3 创建动态库,dll中定义和实现接口
MyDLL.h
#ifndef __MYDLL_DEF__ #define __MYDLL_DEF__ #include#include #include using namespace std; //回调定义 typedef void (CALLBACK* CallBackAdd)(bool bRet); //宏定义函数指针类型 typedef int(*lpAddFun)(int, int); typedef int(*lpAddFunEx)(int, int, CallBackAdd); //函数指针声明 extern lpAddFun addFun; extern lpAddFunEx addFunEx; bool LoadCtrl(CString strPath); void FreeCtrl(); #endif
MyDLL.cpp
#include "stdafx.h"
#include "MyDLL.h"
HINSTANCE g_hCtrlInstance = NULL;
//函数指针
lpAddFun addFun = NULL;
lpAddFunEx addFunEx = NULL;
bool LoadCtrl(CString strPath)
{
g_hCtrlInstance = LoadLibrary(strPath);
if (!g_hCtrlInstance)
{
return false;
}
addFun = (lpAddFun)GetProcAddress(g_hCtrlInstance, "add");
addFunEx = (lpAddFunEx)GetProcAddress(g_hCtrlInstance, "addEx");
return true;
}
void FreeCtrl()
{
FreeLibrary(g_hCtrlInstance);
}
4 应用程序调用DLL
#include "stdafx.h" #include "MyDLL.h" #includevoid CALLBACK CallBackAddFunRet(bool bRet) { if (bRet) { printf("回调成功,bRet=true"); } else { printf("回调成功,bRet=false"); } } int _tmain(int argc, _TCHAR* argv[]) { if (!LoadCtrl(_T("DLL.dll"))) { return -1; } int nSum = addFun(1, 2); int nSumEx = addFunEx(3, 4, CallBackAddFunRet); FreeCtrl(); return 0; }
5 例子下载
上述代码已经实现并且编译通过,有兴趣可以通过如下链接进行下载
(61条消息) C++,动态调用dll,dll也是由c++实现,且实现了回调功能,即应用程序将函数传入到dll,由dll接口调用函数,以实现回调-C++文档类资源-CSDN文库
6 相应接口参考
Dynamic-Link Library Functions - Win32 apps | Microsoft Docs
The following functions are used in dynamic linking.
| Function | Description |
| AddDllDirectory | Adds a directory to the process DLL search path. |
| DisableThreadLibraryCalls | Disables thread attach and thread detach notifications for the specified DLL. |
| DllMain | An optional entry point into a DLL. |
| FreeLibrary | Decrements the reference count of the loaded DLL. When the reference count reaches zero, the module is unmapped from the address space of the calling process. |
| FreeLibraryAndExitThread | Decrements the reference count of a loaded DLL by one, and then calls ExitThread to terminate the calling thread. |
| GetDllDirectory | Retrieves the application-specific portion of the search path used to locate DLLs for the application. |
| GetModuleFileName | Retrieves the fully qualified path for the file containing the specified module. |
| GetModuleFileNameEx | Retrieves the fully qualified path for the file containing the specified module. |
| GetModuleHandle | Retrieves a module handle for the specified module. |
| GetModuleHandleEx | Retrieves a module handle for the specified module. |
| GetProcAddress | Retrieves the address of an exported function or variable from the specified DLL. |
| LoadLibrary | Maps the specified executable module into the address space of the calling process. |
| LoadLibraryEx | Maps the specified executable module into the address space of the calling process. |
| LoadPackagedLibrary | Maps the specified packaged module and its dependencies into the address space of the calling process. Only Windows Store apps can call this function. |
| RemoveDllDirectory | Removes a directory that was added to the process DLL search path by using AddDllDirectory. |
| SetDefaultDllDirectories | Specifies a default set of directories to search when the calling process loads a DLL. |
| SetDllDirectory | Modifies the search path used to locate DLLs for the application. |



