关于 dll 与目标工程的管理及若干注意事项

将 dll 工程和其测试工程建于同一个 solution 下面是一个比较方便的管理方法。

在 dll 工程中,导出函数集中可以放在同一个头文件中,然后作如下处理:

#define DLL_EXPORTS __declspec(dllexport)

所有导出函数前面加上 DLL_EXPORTS 即可。

而测试工程引用的头文件,需要这样声明

#define DLL_IMPORT __declspec(dllimport)

所有导入函数前面加上 DLL_IMPORT 即可。

实际上,测试工程可以直接使用与 DLL 工程同样的头文件,之所以需要 __declspec(dllimport) 来声明,是为了让编译器生成更优的代码:编译器知道导入的函数

来自于 DLL ,可以更快地链接,另外,生成的代码中,对于调用的函数,基地址可以直接基于 dll 来建起,而不是基于整个程序基址寻址,更优。


另外,若使用静态链接的方式,测试工程需要链接 lib 文件,一般可以使用以下的代码:

#ifdef _WIN64
#ifdef _DEBUG
#pragma comment(lib,"../x64/Debug/uCharDetDll_64.lib")
#else
#pragma comment(lib,"../x64/release/uCharDetDll_64.lib")
#endif
#else
#ifdef _DEBUG
#pragma comment(lib,"../Debug/uCharDetDll_32.lib")
#else
#pragma comment(lib,"../release/UchardetDll_32.lib")
#endif
#endif

这样做的好处是,处于同一个 solution 下的两个工程,自然实现了联动。

这里有几点需要重点提出。

第一,使用 param comment(lib,) 指令链接 lib 时,若填入相对路径,则路径是基于 $(ProjectDir) 的,而不是基于这句代码所在的源文件的。

第二,任意的源文件中,include 的文件,若填入相对路径,则路径是基于当前源文件的。

第三,链接的 lib 所在的路径,不影响运行时, dll 的路径。因为 lib 的作用仅仅在于链接,一旦链接完成,生成了 exe 文件,就说明 exe 依赖的函数已经被替换为地址了, lib 文件就没有作用了。当 exe 启动时,相对应的 dll 加载到进程空间,dll 中的函数地址必然是 exe 中指明的地址。如果 dll 找不到,则程序启动失败。最简单的情况下,只需要将 dll 文件与 exe 文件放于同一个目录下即可。

第四,上面一点说的是静态链接,另外一种加载的方式是动态链接/延迟链接,在链接阶段,不需要使用 lib 文件。程序启动后,在运行期间若需要使用到某dll 文件,则再加载 dll,动态从 dll 中寻找依赖函数的地址,保存下来,立即/之后调用。前面有一篇文章详细描写了静态链接和动态链接的差别。

第五,编译是实现文件分别单个编译,各个 .cpp 文件分别生成 obj 文件,而链接是全局的行为,所有 obj 文件链接生成一个 exe 文件。所以,各个实现文件依赖的头文件必须要在源文件中直接或间接地指明,而需要链接的内容则不一定要放在自己的实现文件中。


另一种情形,有一个工程需要依赖于 dll 文件。但是工程分为 32 位,64 位编译模式。此时,可以将 dll 编译的输出命名为 xxx_32.dll 和 xxx_64.dll,在项目属性中的 Linker -> General -> Output File ,设置为 $(OutDir)\$(ProjectName)_32.dll. 如果要进行 64 位编译,则同样也要再设置一次。

可能还存在另一个问题,不方便将 dll 文件放在目标工程的 $(ProjectDir) 目录下,此时运行程序必然失败,因为找不到 dll 文件。此时,可以使用 VS 提供的 "Post-Build Event",在编译-链接完成后,根据需求拷贝文件到 Debug 目录下:

BuildEvent -> Post-Build Event -> Command Line,可以录入这些 cmd 脚本:

cd $(ProjectDir)/thirdpart/uchardet

echo %cd%

copy /b *.dll "$(OutDir)\"

关于以上用到的 VS 宏,可以在上面的配置荐中录入脚本时,右下角可以查看 Macros。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值