选项,填入库文件路径。
图 2 中加红圈的部分为我们添加的 libTe st.lib 文件的路径。
图 2 在 VC 中设置库文件路径 这个静态链接库的例子至少让我们明白了库函数是怎么回事,它们是哪来 的。
我们现在有下列模糊认识了: (1)库不是个怪物,编写库的程序和编写一般的程序区别不大,只是库不 能单独执行; (2)库提供一些可以给别的程序调用的东东,别的程序要调用它必须以某 种方式指明它要调用之。
以上从静态链接库分析而得到的对库的懵懂概念可以直接引申到动态链接库中,动态链接库与静态链接库在编写和调用上的不同体现在库的外部接口定义 及调用方式略有差异。
3.库的调试与查看 在具体进入各类 DLL 的详细阐述之前,有必要对库文件的调试与查看方法 进行一下介绍,因为从下一节开始我们将面对大量的例子工程。
由于库文件不能单独执行,因而在按下 F5(开始 debug 模式执行)或 CTRLF5(运行)执行时,其弹出如图 3 所示的对话框,要求用户输入可执行文件的路径来启动库函数的执行。
这个时候我们输入要调用该库的 EXE 文件的路径就 可以对库进行调试了,其调试技巧与一般应用工程的调试一样。
图 3 库的调试与“运行” 通常有比上述做法更好的调试途径,那就是将库工程和应用工程(调用库的工程)放置在同一 VC 工作区,只对应用工程进行调试,在应用工程调用库中函数的语句处设置断点,执行后按下 F11,这样就单步进入了库中的函数。
第 2 节 中的 libTest 和 libCall 工程就放在了同一
工作区,其工程结构如图 4 所示。
图4 把库工程和调用库的工程放入同一工作区进行调试 上述调试方法对静态链接库和动态链接库而言是一致的。
所以本文提供下载的所有
源代码中都包含了库工程和调用库的工程,这二者都被包含在一个工作区 内,这是笔者提供这种打包下载的用意所在。
动态链接库中的导出接口可以使用 Visual C的 Depends 工具进行查看,让我们用 Depends 打开系统目录中的 user32.dll,看到了吧?红圈内的就是几个 版本的 MessageBox 了!原来它真的在这里啊,原来它就在这里啊! 图 5 用 Depends 查看 DLL 当然 Depends 工具也可以显示 DLL 的层次结构,若用它打开一个可执行文 件则可以看出这个可执行文件调用了哪些 DLL。
好,让我们正式进入动态链接库的世界,先来看看最一般的 DLL,即非 MF C DLL。
VC动态链接库DLL编程(二)--非 MFC DLL 4.非 MFC DLL 4.1 一个简单的 DLL 第 2 节给出了以静态链接库方式提供 add 函数接口的方法,接下来我们来看 看怎样用动态链接库实现一个同样功能的 add 函数。
如图 6,在 VC中 new 一个 Win32 Dynamic-Link Library 工程 dllTest(单击此处下载本工程附件)。
注意不要选择 MFC AppWizarddll,因为用 MFC App Wizarddll建立的将是第 5、6 节要讲述的 MFC 动态链接库。
图 6 建立一个非 MFC DLL 在建立的工程中添加 lib.h 及 lib.cpp 文件,源代码如下: / 文件名:lib.h / ifndef LIB_H define LIB_H extern quotCquot int __declspecdllexportaddint x int y endif / 文件名:lib.cpp / include quotlib.hquot int addint x int y return x y 与第 2 节对静态链接库的调用相似,我们也建立一个与 DLL 工程处于同一工作 区的应用工程 dllCall,它调用 DLL 中的函数 add,其源代码如下: include ltstdio.hgt include ltwindows.hgt typedef intlpAddFunint int //宏定义函数指针类型 int mainint argc char argv HINSTANCE hDll //DLL 句柄 lpAddFun addFun //函数指针 hDll LoadLibraryquot..DebugdllTest.dllquot if hDll NULL addFun lpAddFunGetProcAddresshDll quotaddquot if addFun NULL int result addFun2 3 printfquotdquot result FreeLibraryhDll return 0 分析上述代码,dllTest 工程中的 lib.cpp 文件与第 2 节静态链接库版本完全相同,不同在于 lib.h 对函数 add 的声明前面添加了__declspecdllexport语句。
这 个语句的含义是声明函数 add 为 DLL 的导出函数。
DLL 内的函数分为两种: 1DLL 导出函数,可供应用程序调用; 2 DLL 内部函数,只能在 DLL 程序使用,应用程序无法调用它们。
而应用程序对本 DLL 的调用和对第 2 节静态链接库的调用却有较大差异, 下面我们来逐一分析。
首先,语句 typedef int lpAddFunintint定义了一个与 add 函数接受参数类型和返回值均相同的函数指针类型。
随后,在 main 函数中定义了 lpAddFun 的实例 addFun; 其次,在函数 main 中定义了一个 DLL HINSTANCE 句柄实例 hDll,通过Win32 Api 函数 LoadLibrary 动态加载了 DLL 模块并将 DLL 模块句柄赋给了 h Dll; 再次,在函数 main 中通过 Win32 Api 函数 GetProcAddress 得到了所加载 DLL 模块中函数 add 的地址并赋给了 addFun。
经由函数指针 addFun 进行了对 DL L 中 add 函数的调用; 最后,应用工程使用完 D