您的位置:首页 > 其它

windows下创建并使用动态链接库(.dll)

2016-04-09 15:08 549 查看
定义:

动态链接库(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源码中将全局变量和类封装进普通函数中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  windows dll