DLL中要导出的函数并不一定在包含在dll Entry point的函数中。如果是C++语言编写的dll只需要在导出函数前加上到处extern "C" __declspec(dllexport).dll如果是隐式加载时,Entry point函数的第三个参数为NonZero,而如果是显示被加载时,则此时的参数为Zero。如果进程使用TerminateProcess等方式终结运行,dll Entry中的DLL_PROCESS_DETACH将不被调用。如果dll第一次被加载进进程空间时会调用DLL_PROCESS_ATTACH,但是如果其他线程再度加载这个dll,系统只会增加dll加载的次数,而不会再调用DLL_PROCESS_ATTACH,如果调用TerminateThread来结束主线程,DLL_THREAD_DETACH也不会被调用。
dll加载的两种方式:
a.隐式:
这种方法需要DLL工程经编译产生的LIB文件,此文件中包含了DLL允许应用程序调用的所有函数的列表,当链接器发现应用程序调用了LIB文件列出的某 个函数,就会在应用程序的可执行文件的文件映像中加入一些信息,这些信息指出了包含这个函数的DLL文件的名字。当这个应用程序运行时,也就是它的可执行 文件被操作系统产生映像文件时,系统会查看这个映像文件中关于DLL的信息,然后将这个DLL文件映像到进程的地址空间。这种方式要加载的话,需要把dll放进去运行环境中,而lib和相应的.h头文件都需要在编译Project是被加载进去应用程序中。所以这种情况会导致整个应用程序会增大。
Visual Sdutio中加载DLL的LIB文件的方法有以下三种:
①LIB文件直接加入到工程中
打开项目属性,选择"链接",然后在"常规"中的附加库目录中把lib路径添加上,最后在"输入"中的附加依赖项添加lib的名称。
②通过程序代码的方式
加入预编译指令#pragma comment (lib,”*.lib”),这种方法优点是可以利用条件预编译指令链接不同版本的LIB文件。因为,在Debug方式下,产生的LIB文件是Debug版本,如Regd.lib;在Release方式下,产生的LIB文件是Release版本,如Regr.lib。
当应用程序对DLL的LIB文件加载后,还需要把DLL对应的头文件(*.h)包含到其中,在这个头文件中给出了DLL中定义的函数原型,然后声明。
b.显式:
隐式链接虽然实现较简单,但除了必须的*.dll文件外还需要DLL的*.h文件和*.lib文件,在那些只提供*.dll文件的场合就无法使用,而只能 采用显式链接的方式。这种方式通过调用API函数来完成对DLL的加载与卸载,其能更加有效地使用内存,在编写大型应用程序时往往采用此方式。这种方法编 程具体实现步骤如下:
①使用Windows API函数Load Library或者MFC提供的AfxLoadLibrary将DLL模块映像到进程的内存空间,对DLL模块进行动态加载。
②使用GetProcAddress函数得到要调用DLL中的函数的指针。
③不用DLL时,用Free Library函数或者AfxFreeLibrary函数从进程的地址空间显式卸载DLL.
附加一个介绍dll使用的英文文档:
Using dll