引子
动态链接库DLL文件除了可以实现代码、资源和数据的共享,同时也可以对源代码起保护作用,对于开发者来讲,DLL的生成及调试是程序员必须把握的一种技术,下边通过一个具体的事例vs 调试 找不到dll,演示使用C/C++语言生成及调用DLL文件的方式。这里开发工具选择的是精巧玲珑、启动迅速、精典一代的VC6.0环境,开发完成的目录结构如右图所示:
从目录结构中可以看出,这个事例在“E”盘的“MyDllCode”文件夹下创建了一个工作空间“MyDllCode.dsw”,工作空间中包含了两个项目,分别对应文件夹“MyDllSrc”和“MyDllTest”,其中,后者是动态库的源代码工程,前者是测试代码(调试代码)工程,另外两个文件夹“Debug”和“Release”存放了生成的dll和exe文件。
下边依次详尽说明动态库的创建及调试过程。
创建工作空间和项目
在VC6.0中,选择菜单“文件”-->“新建...”,在弹出的对话框中切换到“工作区”选项页,依次填写工作空间名称和位置信息,如右图所示:
工作区创建完成后,在VC6.0的一侧控制面板上的“FileView”中显示当前的工作区名称为“MyDllCode”,包含的项目个数为0,在工作区上点右键,弹出的右键菜单中选择“添加新工程到工作空间...”,如右图所示:
在弹出的新建工程对话框中,选择工程类型为“Win32Dynamic-LinkLibrary”,工程名称为“MyDllSrc”,切忌选中“添加到当前工作空间”,设置如右图所示:
在弹出的动态库配置对话框中,选择动态库类型为“一个空的DLL工程”即可,如右图所示,这样就完成了动态库源代码工程的创建。
同样的步骤,可以在工作空间中创建一个空的测试代码工程,与动态库源代码工程不同的是,工程类型选择“Win32ConsoleAppliction”的控制台程序,工程名称为“MyDllTest”。
工作空间的工程项目创建完成后,在VC6.0的一侧控制面板上的“FileView”中显示情况如右图所示,此时包含2个工程项目,皆为空工程,未包含任何源代码文件:
设置工程输出目录
本事例既包含了动态库源代码工程,也包含了测试代码工程(即调试工程),为易于调试,将两个工程的输出文件目录设为同一个目录,如都设为与工作空间“MyDllCode.dsw”同一个目录,这样免去了将动态库dll文件自动拷到exe所在的目录下的麻烦。如对于“Debug”模式,在VC6.0中选择菜单“工程”-->“设置”或直接按“Alt+F7”快捷键,在弹出的工程对话框中选中工程“MyDllSrc”,在左侧的“连接”选项卡页更改输出文件名,由原先默认的“Debug/MyDllSrc.dll”修改为“../Debug/MyDll.dll”,正式生成的“MyDll.dll”文件更改为当前工程所在目录的上级目录的“Debug”文件夹中。同样形式更改工程“MyDllTest”文件输出目录为“../Debug/MyDllTest.exe”如右图所示:
对于“Release”模式,同前面形式完全相同,分别将工程“MyDllSrc”和“MyDllTest”的文件输出目录更改为“../Release/MyDll.dll”和“../Release/MyDllTest.exe”。
编撰动态库工程源代码文件
新建头文件“MyDll.h”,在VC6.0中选择菜单“文件”-->“新建...”,在弹出的新建文件对话框中设置如右图所示,切忌勾选“添加到工程”为“MyDllSrc”。
在新建的“MyDll.h”文件中,代码如下:
同样的方法,新建C++源文件“MyDll.cpp”,代码如下:
在动态库工程中,定义并导入了一个函数“MyFunc”,该函数形成等间隔的数据向量并返回数据向量的最后一个值和状态信息。在头文件中定义宏“EXPORT”为“extern"C"__declspec(dllexport)”,说明该函数调用约定为“C”方式vs 调试 找不到dll,在其它编程语言中调用该函数时,调用约定必须一致。编译运行后即可得到在“E:\MyDllCode\Debug”目录下得到动态库文件“MyDll.dll”。
编撰测试工程(调试工程)源代码文件
同编撰动态库源代码文件类似,新建一个测试代码C++源文件“main.cpp”,切忌勾选“添加到工程”为“MyDllTest”,代码如下:
代码中,通过“#include"../MyDllSrc/MyDll.h"”引入动态库的头文件,通过#pragma宏引入lib文件,这里注意,路径必须设置正确。编译运行后即可得到在“E:\MyDllCode\Debug”目录下得到可执行程序“MyDllTest.exe”文件,运行结果如下:
可见,调试代码工程中,早已正确调用了“MyFunc”函数。
推论
前面给出了在VC6.0中创建及调试动态库的完整过程,在其它如VS2008、VS2010等IDE中,配置环节也是类似的。另外,须要说明的是,因为本事例将动态库工程和调试工程放到了同一个工作空间中,为此,在单步调试中,若在调用函数的行设置断点,则不需作额外的设置,会手动步入到动态库工程的源代码“MyDll.cpp”中,观察“MyFunc”函数的执行情况。