首先我们明白“DLL”编程是很重要的:在windows API 中有3个重要的DLL
Kernel32.dll:它包含用于管理内存、进程和线程的各个函数;
User32.dll: 它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;
GDI32.dll:它包含用于画图和显示文本的各个函数。
对于“动态链接库”和“静态链接库”的区别:简单来说,前者在编译的时候链接的是生成的 DLL.lib “引导库”文件,不是.dll 本身。DLL.lib “引导库”文件中包含了 .dll中的变量信息,函数声明信息,还有其他的一些信息、、、在程序运行的时候还需要通过一个路径去找.dll库的所在(一般的寻找顺序是:Debug ---> 本目录 --- >system32 --- > system --- > 其他系统目录--- > Dll.lib提供的目录),然后完成程序的正常运行。同时在DLL加载进客户端程序的时候,又分为两种行为:第一种是将库直接写入 Link中,那么程序运行时就加载了此库,但是很多情况下是用不了那么的函数的,所以很占内存,所以第二种就是动态加载DLL。
下面看看DLL编程:
我们任意生成一个DLL程序,链接后会生成3个重要文件:
1、.dll:主要文件,包含最多的信息,函数的实现、、、
2、.exp:包含的是输出信息、、、
3、.lib:包含的是输入信息、、、
对于函数能够被客户端程序调用,我们需要注意很多问题:
1、
在 dll.h 中:
#ifdefDLL1_API
#else
#define DLL1_API _declspec( dllimport ) //注意:dllimport是外部函数被使用的必须条件
#endif
DLL1_API int add( int a, int b);
DLL1_API int subtract( int a, int b );
在dll.cpp中:
#define DLL1_API _declspec( dllexport )
int add( int a, int b)
{
}
int subtract( int a, int b )
{
}
我们可以解释一下:if 是内部程序调用的话,我们知道,由于在cpp中已经定义了
#define DLL1_API _declspec( dllexport )
那么就不需要在定义DLL1_API了。但是对于外部程序而言,只要客户端没有定义,那么我们需要定义#define DLL1_API_declspec( dllimport ),对于客户端程序调用的条件!
注:对于_declspec( dllimport )和_declspec( dllexport )在上篇已经说过、、、
2、
dumpbin –exports Dll1.dll 可以看输出( 导出 )信息
dumpbin –imports Dll1.dll 可以看输入( 导入 )信息
我们可以看到:原本我的程序代码中的函数是:
DLL1_API int add( int a, int b);
DLL1_API int subtract( int a, int b );
class DLL1_APIPoint
{
};
我们可以看到不仅仅是函数,甚至连类的名称都被改变咯!呵呵~对于C++客户端程序而言,这样的调用是没有问题的,但是对于其他的呢?例如C客户端,那显然是不行的!我们可以想到一个办法解决C客户端的问题:那就是但我们在定义宏的时候加上:extern “C” 是可以的:
但是这是对于C语言的标准而言的额,对于其他的是不行的,例如对于WINWPI的标准 _stdcall还是不行的,自己可以尝试!
那么我们怎么解决呢!
我们就需呀-------à 模块定义文件(.def)
LIBRARY
EXPORTS
add
subtract
一个.def文件中只有两个必需的部分:LIBRARY 和 EXPORTS。
第一行:''LIBRARY''是一个必需的部分。它告诉链接器(linker)如何命名你的DLL。
第二行:EXPORTS也是必须部分,下面每行分别是函数名。
此处只是简单介绍、、、具体的看 MSDN、、、
对于我们这样的操作,可以尝试一下,即使是其他的标准,例如:
int _stdcall add( int x, int y)
int _stdcall subtract( int x, int y )
最后导出的函数名也是 add 和subtract,不信自己尝试,O(∩_∩)O~
同样这样的操作对于“导出类”也是可以的哦~~~
3、
首先我们需要函数:LoadLibrary,其返回值是HINSTANCE
然后还有很重要的一点是:我们需要获取函数的地址,那么我们在此处的操作是利用函数指针来处理:typedef int (_stdcall *INSTANCEADD )( int a, int b ); // 此处我们处理add函数
代码如下:
HINSTANCE hInst;
hInst = LoadLibrary( "Dll2.dll");
typedef int ( _stdcall *INSTANCEADD )( int a, int b);
INSTANCEADD ADD=( INSTANCEADD )GetProcAddress( hInst,MAKEINTRESOURCE( 1 ));
if ( !ADD)
{
}
CString str;
str.Format( "5 + 3 = %d", ADD( 5, 3 ) ); // 调用外部函数( 注意此处是 ADD,不是 add )
MessageBox( str );
FreeLibrary( hInst);
}
这些就是基础DLL编程,大侠们见笑咯~~~