windows下创建并使用动态链接库(.dll)
2016-04-09 15:08
549 查看
定义:
动态链接库(dll)是一个包含可由多个程序同时使用的代码和数据的库。动态链接库不能直接运行,也不能接收消息。它们是一些独立的文件,其中包含能被可执行程序或其它DLL调用来完成某项工作的函数或是数据
2、添加如下三个文件
DllMain.cpp
在DllOne.dll的创建过程中,使用的是_declspec( dllexport )方式导出函数的,其实还有另一种导出函数的方式,那就是使用导出文件(.def)。
隐式加载
1、新建一个名为DllTest的win32控制台工程。
2、将DllOne.lib和DllOne.h拷贝到DllTest的工程目录下。
3、将DllOne.lib添加到工程属性中,如下所示:
4、使用Dll中的函数和数据。
Test.cpp
显示加载
1、新建一个名为DllTest的win32控制台工程。
2、使用LoadLibrary()加载Dll,如下所示:
Test.cpp
在显示加载示例代码中只调用了dll中的GetAbs普通函数,这是因为在显示加载时是无法直接调用dll中的全局变量和类的,GetProcessAddress函数只能导出普通函数。所有如果想在显示加载时也使用dll的全局变量和类,则需要在dll源码中将全局变量和类封装进普通函数中。
动态链接库(dll)是一个包含可由多个程序同时使用的代码和数据的库。动态链接库不能直接运行,也不能接收消息。它们是一些独立的文件,其中包含能被可执行程序或其它DLL调用来完成某项工作的函数或是数据
一、创建动态链接库
1、新建一个名为DllOne的win32工程,并设置Application type为DLL,创建一个DLL工程。2、添加如下三个文件
DllMain.cpp
#include<windows.h> //DllMain函数在DLL被加载和卸载时被调用,在单个线程启动和终止时,DllMain //函数也被调用。参数ul_reason_for_call指明了调用DllMain的原因。 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; }DllOne.h
#include<string> using namespace std; //DLLONE_EXPORTS定义在工程属性的command line中。 //数据或者函数需要被导出时,则要在其定义前加上__declspec(dllexport)。这里用了宏定义来简化编码。 #ifdef DLLONE_EXPORTS #define DLLONE_API __declspec(dllexport) #else #define DLLONE_API __declspec(dllimport) #endif #define EXTERN_C extern "C" //使该dll能被c语言程序调用 class DLLONE_API CFirstDll { public: CFirstDll() { m_spDllName = new string(""); } ~CFirstDll() { delete m_spDllName; } void SetDllName(const string &sName); void PrintDllName(); private: //如果定义的是一个string变量,则在其他程序中 //调用定义这个类的对象时,会提示这个string变量是bad ptr。 //原因参考http://bbs.csdn.net/topics/210005206 string *m_spDllName; }; EXTERN_C DLLONE_API int g_iValue;//全局变量 EXTERN_C DLLONE_API int GetAbs(int iValue);//普通函数DllOne.cpp
#include"DllOne.h" #include<cmath> #include<iostream> DLLONE_API int g_iValue = 0; DLLONE_API int GetAbs(int iValue) { return abs(iValue); } void CFirstDll::SetDllName(const string &sName) { *m_spDllName = sName; } void CFirstDll::PrintDllName() { cout << *m_spDllName << endl; }编译后就可以生成DllOne.dll和DllOne.lib。DllOne.lib包含被DLL导出的函数和变量的符号名,而DllOne.dll包含实际的函数和数据。
在DllOne.dll的创建过程中,使用的是_declspec( dllexport )方式导出函数的,其实还有另一种导出函数的方式,那就是使用导出文件(.def)。
二、使用动态链接库
在使用DLL时有两种方式:隐式加载和显示加载。隐式加载
1、新建一个名为DllTest的win32控制台工程。
2、将DllOne.lib和DllOne.h拷贝到DllTest的工程目录下。
3、将DllOne.lib添加到工程属性中,如下所示:
4、使用Dll中的函数和数据。
Test.cpp
#include"DllOne.h" #include<iostream> using namespace std; void main() { g_iValue = -3; int i = GetAbs(g_iValue); cout << i << endl; CFirstDll myDll; myDll.SetDllName("implicit linking"); myDll.PrintDllName(); while(1); }5、将DllOne.dll添加到DllTest.exe所在的目录。
显示加载
1、新建一个名为DllTest的win32控制台工程。
2、使用LoadLibrary()加载Dll,如下所示:
Test.cpp
#include"windows.h" #include<iostream> using namespace std; typedef int (*AbsFunc)(int iValue);//定义一个函数指针 void main() { HMODULE hDll = LoadLibrary(L"DllOne.dll");//加载dll库 if (hDll!=NULL) { //获取dll中GetAbs函数的地址 AbsFunc MyAbs = (AbsFunc)GetProcAddress(hDll, "GetAbs"); int i = MyAbs(-4); cout << i << endl; //动态加载时,不能通过如下方式使用全局变量和类 // g_iValue = 1; // CFirstDll myDll; // myDll.SetDllName("implicit linking"); // myDll.PrintDllName(); while(1); FreeLibrary(hDll); } }3、将DllOne.dll添加到DllTest.exe所在的目录。
在显示加载示例代码中只调用了dll中的GetAbs普通函数,这是因为在显示加载时是无法直接调用dll中的全局变量和类的,GetProcessAddress函数只能导出普通函数。所有如果想在显示加载时也使用dll的全局变量和类,则需要在dll源码中将全局变量和类封装进普通函数中。
相关文章推荐
- 如何重装TCP/IP协议
- Windows 8 官方高清壁纸欣赏与下载
- 谁是桌面王者?Win PK Linux三大镇山之宝
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows Clang开发环境备忘
- 从Windows系统下访问Linux分区相关软件
- FREEBASIC 编译可被python调用的dll函数示例
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows下搭建本地SVN服务器
- 使用Windows原生命令一键清空剪贴板
- 利用开源软件打造自己的全功能远程工具
- Visual Studio 2012 示例代码浏览器 - 数以千计的开发示例近在手边,唾手可得
- Visual Studio 2012 示例代码浏览器 - 数以千计的开发示例近在手边,唾手可得
- 微软镜像下载
- windows server域用户提升到本地更高权限组中的方法
- 使用命令修改注册表键值及权限