第十九课

动态链接库程序的编写。静态库与动态库的区别,以及调用程序在链接静态库和动态库时的区别。如何利用工具查看动态链接库输出的函数,Depends工具的使用,C++编译器名字改编技术对动态链接库输出函数的影响,extern "C"的用法,利用模块定义文件来解决C++名字改编的问题。用typedef定义指向函数的指针类型,如何获得动态连接库里的函数的指针。

动态链接库

从微软推出第一个版本的Windows操作系统以来,动态链接库(DLL)一直是Windows操作系统的基础。

动态链接库通常都不能直接运行,也不能接收消息。它们是一些独立的文件,其中包含能被可执行程序或其它DLL调用来完成某项工作的函数。只有在其它模块调用动态链接库中的函数时,它才发挥作用。

Windows API中的所有函数都包含在DLL中。其中有3个最重要的DLLKernel32.dll,它包含用于管理内存、进程和线程的各个函数;User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;GDI32.dll,它包含用于画图和显示文本的各个函数。

静态库和动态库

态库:函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件(.EXE文件)

在使用动态库的时候,往往提供两个文件:一个引入库和一个DLL。引入库包含被DLL导出的函数和变量的符号名,DLL包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中,在运行的时候,再去加载DLL,访问DLL中导出的函数。

Dll导出函数     _declspec(dllexport)  int subtract(int a, int b)   在实现部分定义

#ifdef  MYDLL

#else

#define MYDLL  extern "C"  _declspec(dllimport)   

#endif

_declspec(dllimport)   声明是从动态链接库插入的。表明是从动态链接库中导入的

#define DLL1_API extern "C" _declspec(dllexport)      语言的方式导出

class  DLL1_API  Point   导出类

{

};

GetForegroundWindow该函数返回前台窗口(用户当前工作的窗口)。

GetActiveWindow 只是获取当前程序中(严格地说是线程中)被激活的窗口;
GetForegroundWindow 是获取当前系统中被激活的窗口.

 两个函数的级别不一样一个是线程级、一个是系统级.

 被激活的窗口不一定是顶层窗口(最上面的窗口).

class  Point             导出类的成员函数

{

public:

DLL1_API void output(int x,int y);

void test();

};

{

int _stdcall add(int a,int b)           函数的标准调用

需要一个模块定义文件

{

Dll2.def

LIBRARY Dll2

EXPORTS

Add           导出的函数名

Subtract        导出的函数名

}

}

显示加载链接库,用的时候才加载,效率更高

HINSTANCE hInst;

hInst=LoadLibrary("Dll3.dll");       加载动态链接库

typedef int (/*_stdcall*/ *ADDPROC)(int a,int b);          要注意导出函数的调用约定

ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add");   得到链接库的add函数

ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));//根据导出库的序号访问函数

if(!Add)

{

MessageBox("获取函数地址失败!");

return;

}

CString str;

str.Format("5+3=%d",Add(5,3));             使用动态链接库的函数add

MessageBox(str);

FreeLibrary(hInst);

BOOL FreeLibrary(          //释放动态链接库

  HMODULE hModule   // handle to DLL module

);

DllMain

BOOL WINAPI DllMain(

  HINSTANCE hinstDLL// handle to the DLL module

  DWORD fdwReason,    // reason for calling function

  LPVOID lpvReserved   // reserved

);

exe有个main或者WinMain入口函数一样,DLL也有一个入口函数,就是DllMain。以“DllMain”为关键字,来看看MSDN帮助文档怎么介绍这个函数的。   The DllMain function is an optional method of entry into a dynamic-link library (DLL)。(简要翻译:对于动态链接库,DllMain是一个可选的入口函数。)这句话很重要,很多初学者可能都认为一个动态链接库肯定要有 DllMain函数。其实不然,像很多仅仅包含资源信息的DLL是没有DllMain函数的。

系统是在什么时候调用DllMain函数的呢?静态链接时,或动态链接时调用LoadLibraryFreeLibrary都会调用DllMain函数。DllMain的第三个参数fdwReason指明了系统调用Dll的原因,