windows编程之动态链接库的使用
来源:互联网 发布:html css js源码下载 编辑:程序博客网 时间:2024/05/23 12:55
当我们进行程序的编写的时候,经常需要将一些资源进行重复利用等操作。于是,微软就提出了DLL(动态链接库),它可以很好的将资源进行重复利用。
当一个进程加载一个DLL的时候呢,一般都会执行DllMain这个动态链接库的入口点(有时候不会,后面再讲),来看下它的声明:
BOOL WINAPI DllMain( HINSTANCE hinstDLL, // dll模块的内存基址 DWORD fdwReason, // 加载本dll的原因 LPVOID lpvReserved // 系统保留);其中,fdwReason有四个原因,第一个是DLL_PROCESS_ATTACH,表示进程加载本dll时。第二个是DLL_THREAD_ATTACH,表示线程加载本dll时。第三个是DLL_THREAD_DETACH,进程卸载本dll时,第四个是DLL_PROCESS_DETACH,线程卸载本dll时。
因为它是被刚加载或卸载的时候调用的,因此我们可以在该函数内写一些初始化的工作和释放资源的工作。
在DLL中,我们编写完要共享的代码后,我们需要对这些代码进行导出,变成导出函数或类等才能被我们共享使用。下面来介绍两种DLL导出函数的两种方式。
第一种导出方式是使用def文件,里边的内容格式如下:
LIBRARY 项目名EXPORTS导出函数名1导出函数名2写完之后,将后缀名改为.def格式,将其添加到工程里边,然后在VS里边右键属性----配置信息/链接器/输入/模块定义文件这一栏添加该文件即可,然后我们生成解决方案,我们的函数就被导出了。我们可以使用Dependency Walker工具来查看是否已经被导出了。
第二种导出的方式是使用__declspec(export)的方式。我们在要导出的函数名前添加这样一句话即可。如果你使用的是VS的C++编译器,最好在该句话前在添加一句extern "C"来声明是以C语言的标准来进行编译的,为什们呢?因为VS的C++编译器会自动的将我们的函数名以微软的方式添加一些信息。以下是一个声明导出函数的例子:
extern "C" __declspec(dllexport) DWORD TestFun(int a, int b){return a + b;}
知道了怎样在dll工程中导出一个函数后,我们在来看下如何在别的工程中使用我们导出的函数。调用导出函数,也有两种方式,一种是隐式调用,一种是显示调用。
先来看下隐式调用。在我们的dll工程中,生成解决方案后,会生成一个dll文件和一个.lib文件。其中.dll文件里边包含了代码的实现等信息。而.lib文件则包含了函数的内存地址信息,用于指明我们的函数在哪个内存地址。因此,我们可以链接这个lib文件来使用我们的函数。在此之前呢,我们还要声明一下我们要使用哪个函数,然后再来链接,声明时要在函数前加一句__declspec(dllimport)表示导入一个函数,下面是一个示例:
extern "C" __declspec(dllimport) int TestFun(int a, int b);<span style="white-space:pre"></span>//声明一个导入函数#pragma comment(lib,"testLib.lib")<span style="white-space:pre"></span>//链接我们的lib文件显式调用。假设我们没有.lib文件,那么我们应该使用显示调用。显示调用就是调用LoadLibrary函数来动态的加载一个dll文件,然后用GetProcAddress来确定导出函数的地址。它们的声明如下:
HMODULE LoadLibrary( LPCTSTR lpFileName // 模块名);FARPROC GetProcAddress( HMODULE hModule, // 上一个函数的返回值 LPCSTR lpProcName // 函数名);下面是一个显示调用的示例代码:
#include <stdio.h>#include <windows.h>//定义一个函数指针,返回值和参数要与导出的函数相同typedef int(*lpTestFun)(int,int);int _tmain(int argc, _TCHAR* argv[]){HMODULE hDll;lpTestFun testFun;//加载一个dllhDll = LoadLibrary("testLib.dll");if (hDll){//获取要导出函数的地址testFun = (lpTestFun)GetProcAddress(hDll, "testFun");if (testFun){printf("testFun result:%d\n", testFun(3, 2));}}return 0;}
在文章开头讲过我们可能不需要DllMain这个函数入口点,当我们动态的加载一个函数时,除了调用LoadLibrary这个函数外,我们还可以调用它的加强版LoadLibraryEx,其声明如下:
HMODULE LoadLibraryEx( LPCTSTR lpFileName, // 文件名 HANDLE hFile, // 系统保留,必须为NULL DWORD dwFlags // 一些标志位);该函数的第三个参数里边,有一个DONT_RESOLVE_DLL_REFERENCES这个标志位,它表示当使用这个标志位的时候呢,加载一个Dll时,程序不会执行我们的DllMain这个入口点函数。为什么要使用这个函数呢,假如我们在网上下载了一个dll,它可能在DllMain里边写了一些邪恶的代码,如果我们调用LoadLibrary去加载时,就可能引发一些严重的后果。这时加强版就起到了作用。
- windows编程之动态链接库的使用
- 初识windows编程之动态链接库
- Windows 动态链接库编程
- Windows 动态链接库编程
- Windows 动态链接库编程
- Windows 动态链接库编程
- Windows动态链接库DLL的使用
- Windows下动态链接库的使用
- Windows API编程之动态链接库(DLL)
- Windows API编程之动态链接库(DLL)
- Windows API编程之动态链接库(DLL)
- Windows API编程之动态链接库(DLL)
- Windows编程 - 遍历程序使用的动态链接库(dll) 代码(C++)
- Windows下的VC++动态链接库编程
- Windows动态链接库编程笔记
- Windows的动态链接库
- windows下qt使用动态链接库的方法
- windows下动态链接库的创建和使用
- Long Names Are Long
- 算法竞赛入门经典:第6章例题
- [阶段一]Java面向对象(4)
- CSS3新属性
- 【c++程序】全局变量和局部变量汇总
- windows编程之动态链接库的使用
- 大话设计模式———c++反射机制实现
- mssql 按月统计,按日统计,按周统计,按季度统计
- 图像的基本函数运算
- Linux学习之路
- 汇编角度解释溢出段错误
- 标签、css、
- toascii字符串转换函数应用实例
- iOS 10 新特性