[Win32] DLL的开发和使用
来源:互联网 发布:pp助手 mac 铃声制作 编辑:程序博客网 时间:2024/05/21 11:35
为何要开发DLL:
1。DLL可以在程序需要时加载或卸载,可以实现软件的“模块化开发”。
2。可以达到一些特殊目的,比如通过DLL注入来进入另一个进程的空间,Hook它的函数,等等。
所以不管怎么说,DLL是Windows开发中相当重要的一部分。
1。DllMain
MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx
BOOL WINAPI DllMain( _In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved);
hinstDLL:DLL模块的实例句柄
fdwReason:可以是下列值之一:
DLL_PROCESS_ATTACH:DLL 被加载到进程启动或通过调用 LoadLibrary 到当前进程的虚拟地址空间。Dll 可以利用这个机会来初始化。
DLL_PROCESS_DETACH:正在从调用进程的虚拟地址空间卸载 DLL。
DLL_THREAD_ATTACH:当前进程创建一个新线程。请注意,DLL 入口点函数调用时使用此值只由线程创建后由进程加载的 DLL。当 DLL 加载时使用 LoadLibrary 时,现有的线程不调用新加载的 dll 入口点函数。
DLL_THREAD_DETACH:一个线程正在退出。
lpvReserved:
如果 fdwReason 是 DLL_PROCESS_ATTACH,NULL表示DLL是动态载入的,非NULL说明是静态载入的。
如果 fdwReason 是 DLL_PROCESS_DETACH,NULL表示是调用FreeLibrary使DLL卸载的,非NULL说明是进程即将终止而调用的。
返回值:当系统调用 DllMain 函数的 DLL_PROCESS_ATTACH 值时,如果初始化成功,该函数返回TRUE,如果初始化失败,返回FALSE(导致LoadLibrary失败或进程加载失败)。
如果不是非常有必要,不要在DLL中静态调用非Kernel32.dll和非Ntdll.dll中的函数!
原因:调用时相应DLL可能没有加载,因此会出现无法预料的问题。
2。导出函数
DLL中的函数之所以能被程序调用,是因为DLL可以把自身的函数导出去给其他程序调用,这就是为什么用DLL可以进行“模块化开发”的原因。
导出函数可以用两种方法导出
1。在函数声明或定义上显示声明为:_declspec(dllexport)
2。使用DEF文件
比如些一DLL:
#include "stdafx.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;}extern "C" _declspec(dllexport) int WINAPI a(int i){return (++i);}
extern "C"作用:禁用函数重载以避免C++编译器不按照符号修饰约定导出符号。
编译后会生成DLL文件和Lib文件,如果是控制台编译,先写一def文件,然后使用lib命令将def打包成lib,其中def文件这样写:
LIBRARY DLL名字(很重要,这个会写入lib,在exe编译时dll名称会写入PE文件导入表)EXPORTS 函数1函数2。。。。
lib.exe从def导出lib的命令为:lib.exe /def:xxx.def(如果从obj导出直接lib加上obj文件即可)
#pragma comment(lib,"名称.lib")
extern "C" _declspec(dllimport) int WINAPI a(int i);
int _tmain(int argc, _TCHAR* argv[]){int i=a(1);char a[10];_itoa(i, a, 10);MessageBoxA(NULL, a, "静态调用结果", 0);return 0;}
void calldll(){typedef int (WINAPI *A)(int i);//定义函数指针HMODULE hdll = LoadLibrary(TEXT("DLL.dll"));//加载DLLif (hdll != NULL){A aa = (A)GetProcAddress(hdll, "_a@4");//获取函数地址if (aa != NULL){int i = aa(1);//调用函数char a[10];_itoa(i, a, 10);MessageBoxA(NULL, a, "动态调用结果", 0);}}//....FreeLibrary(hdll);//不需要时可以卸载DLL}
_a(at)4
_函数名@函数参数所需堆栈大小
- [Win32] DLL的开发和使用
- 创建Win32 DLL的步骤和使用
- MFC win32 Dll的创建和使用
- 动态链接库(Win32 DLL的创建和使用)
- win32 dll 和MFC dll的区别
- win32 dll 和MFC dll的区别
- 关于win32 Dll开发的进一步讨论
- WIN32 DLL中使用MFC的问题
- Win32 dll 的简单创建与使用
- win32 dll导出类的使用
- 建立WIN32 DLL,并使用静态加载和动态加载
- dll转exe方法 适用win32下的开发 C++
- Win32 DLL中使用GDI+
- Win32 DLL中使用MFC
- win32 dll中使用cstring
- 在WIN32 DLL中使用MFC库遇到的问题
- win32下,lib和dll的区别与制作
- 动态链接库(DLL)的开发和使用
- 一个妹子图应用客户端android源码
- linux相关笔记
- OpenGL深度测试带来的问题----Z冲突
- 算法竞赛入门经典:第八章 高效算法设计 8.16贪心之乘船问题
- Fight Repetition
- [Win32] DLL的开发和使用
- NSPredicate的用法
- Welcome to the Real World
- 使用Swift创建一个SOAP的请求
- JS动画封装
- 算法竞赛入门经典:第八章 高效算法设计 8.17 贪心之选择不相交区间
- 根据遍历序列构建二叉树,并转换成双向链表
- AE开发之路(二)
- iOS开发之MVC