简介
动态链接库(DLL,全称Dynamic Link Library)进程之间共享使用的函数库。动态链接库提供了一种方法,是进程可以调用不属于其自身可执行代码的函数。函数的可执行代码位于一个DLL中,当调用DLL中的方法时,进程由原本自身的代码执行到DLL中。DLL有助于程序模块化,减少重复开发。
在这之前已经提到的多次的 kernel32.dll ,也即 windows 的核心DLL,我们进行 windows 编程开发中很多函数都是从其中导出。
编写 DLL
1) 新建项目
【文件】->【新建】->【项目】->选择【win32 项目】->【下一步】->【DLL 空项目】
新建项目的目录要记一下,等会会用到。
2)开始编写 DLL
dll.h
#ifdef MYDLL_EXPORTS #define MYDLL_API _declspec(dllexport) #else #define MYDLL_API _declspec(dllimport) #endif // 声明自定义导出函数 MYDLL_API void helloDLL(void);
dll.c
#include <windows.h>// for MessageBox #include "dll.h" // 引用导出定义 // DLL入口函数 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { switch(dwReason) { // 动态链接库映射到某个进程的地址空间 case DLL_PROCESS_ATTACH: /** * 当DLL刚被加载时触发(LoadLibrary),此处专门用来做初始化工作, * 如果初始化失败可以返回 false 这样DLL就不会被继续加载了 **/ break; // 应用程序创建新的线程 case DLL_THREAD_ATTACH: break; // 应用程序某个线程正常终止 case DLL_THREAD_DETACH: break; // 动态链接库将被卸载 case DLL_PROCESS_DETACH: /** * 当DLL将要被卸载时触发(FreeLibrary),此处专门用来做清理工作 * 如关闭文件,释放内存空间等 **/ break; } return 1; } void helloDLL(void) { MessageBox(NULL, TEXT("Hello DLL~"), TEXT("Title"), MB_OK); }
编写好之后 F7 生成(visual studio 2008以上),到项目的 Debug 目录下找到生成的 DLL 一般是 【项目名.DLL】
调用 DLL
再新建一个普通的【空项目】就可以了
#include <stdio.h> #include <windows.h> // 指向函数的指针类型 typedef void (*fun_pointer)(void); // main VOID main(VOID) { HINSTANCE hDLL; BOOL flagGetFun = FALSE; fun_pointer p; // 加载 Dll hDLL = LoadLibrary(TEXT("DLLTEST.dll")); // 判断是否加载成功 if (hDLL != NULL) { printf("模块加载成功n"); // 获得指定导出函数的地址 p = (fun_pointer) GetProcAddress(hDLL, "helloDLL"); // 判断是否成功 if (NULL != p) { printf("函数获取成功,准备调用函数n"); p(); // 成功则调用DLL中的函数 }else { printf("函数获取失败!n"); printf("error: %un", GetLastError()); } // 释放DLL if (!FreeLibrary(hDLL)) { printf("DLL释放失败n"); printf("error: %un", GetLastError()); } }else { printf("模块加载失败!n"); printf("error: %un", GetLastError()); } system("pause"); }
编写好之后,点击生成,将开始的 DLL 文件拷贝到该项目的 Debug 目录(与exe同一个目录),接着双击执行即可。
博主快讲讲 #ifdef MYDLL_EXPORTS的意思是如果定义了MYDLL_EXPORTS就执行下面的#define MYDLL_API _declspec(dllexport),否则执行#define MYDLL_API _declspec(dllexport),但是前面没有定义MYDLL_EXPORTS,难道最终执行的是#define MYDLL_API _declspec(dllexport吗
赞赞
博主你好,我编译dll.h的时候有个警报: warning C4273: “helloDll”: dll 链接不一致
google了下找到解决方法了,
加上
#define MYDLL_EXPORTS
这句就ok了,非常感谢博主写适合新手的文章!
#define MYDLL_EXPORTS
#ifdef MYDLL_EXPORTS
#define MYDLL_API _declspec(dllexport)
#else
#define MYDLL_API _declspec(dllimport)
#endif
另外还有一个问题就是创建第二个空项目的时候容易搞错,应该指明是windo控制台程序【新手路过……】
赞赞
建议在头文件中MYDLL_API void helloDLL(void);的前面加上extern “C”,即是extern “C” MYDLL_API void helloDLL(void);否则在vc++6.0中会导致 p=(fun_pointer) GetProcAddress(hDLL,”helloDLL”);返回值为空,也就是说在DLL中找不到helloDLL函数,因为不加 extern “C”的话,vc++6.0会按照c++语言进行编译,会把helloDLL的函数名改变掉,自然就找不到了
赞赞
按代码操作成功了。太好了
赞赞