如何将C++Builder应用程序拆分为DLL?

3
我曾多次被告知应该考虑将我的应用程序的部分拆分成单独的DLL(以加快链接速度等),现在正试图弄清楚如何操作。
我理解我需要在计划使用的每个头文件声明中添加“__declspec(dllexport)”标记。这似乎很繁琐,但还是可行的。
如何运行应用程序+ DLL?在一个简单的测试项目中,我发现唯一可行的方法是手动将DLL从DLL项目的生成输出目录复制到exe项目的生成输出目录。我知道可以设置后期构建步骤来完成此操作,但我希望IDE有某种自动化方式,使应用程序项目在它们属于同一项目组时使用DLL项目。
如何调试应用程序+ DLL?我知道可以在“项目”-“选项”-“调试器”下指定DLL的主机应用程序,但到目前为止,我只能找到一次调试一个项目的方法。我真的希望能够在代码库的任何地方设置断点并单步执行任何代码(而不是停留在项目边界处),但我无法找到如何实现这一点的方法。
1个回答

3
我知道我需要在每个头文件声明中添加__declspec(dllexport),这似乎很繁琐,但是可以做到。
你应该在DLL的头文件中创建一个#define,当该头文件由DLL项目编译时,它映射到dllexport,而在其他项目中编译时则映射到dllimport。例如:
#ifndef MyDLLH
#define MyDLLH

#ifdef _BUILDING_DLL_
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif

MY_EXPORT type callingconvention SomeFunc(parameters);
#ifdef __cplusplus
}
#endif

#endif

然后你可以在你的 DLL 项目中定义 _BUILDING_DLL_,要么在项目选项的条件列表中,要么在头文件的任何 #include 语句之前的代码中,例如:

#define _BUILDING_DLL_
#include "MyDll.h"

如何运行应用程序和DLL文件?
DLL项目生成一个.lib文件,用于静态链接到DLL导出的函数。您可以将该.lib文件添加到您的EXE项目中,然后像调用任何其他函数一样调用DLL函数。或者您可以在运行时使用Win32 API LoadLibrary()和GetProcAddress()函数动态加载DLL函数,在这种情况下,您根本不使用.lib文件。
在一个简单的测试项目中,我发现唯一可行的方法是手动将DLL从DLL项目的构建输出目录复制到exe项目的构建输出目录。
EXE文件夹是操作系统查找DLL的第一个位置,但它并不是操作系统查找DLL的唯一位置。MSDN文档介绍了DLL在运行时的定位方式: Dynamic-Link Library Search Order 我知道我可以设置一个后置构建步骤来完成这个工作,但我希望IDE有某种自动化方式让应用程序项目在它们属于同一项目组的情况下使用DLL项目。
只是参与同一项目组是不够的。这些项目彼此独立编译。但是,您可以将DLL项目设置为EXE项目的依赖项(或者只需确保DLL项目在构建顺序中高于EXE项目),以便首先编译DLL,然后使用DLL的PostBuild事件将编译的.lib和.dll二进制文件移动到所需位置,并最后将DLL的已编译.lib文件添加到EXE项目中,以便运行时使用DLL。
“我如何调试应用程序+ DLL?”您有几个选择:
要仅调试DLL本身,请将DLL项目加载到IDE中,进入运行参数,将编译后的EXE设置为主机应用程序。然后,您可以像运行EXE项目一样运行DLL项目。一旦将DLL加载到内存中,EXE将被执行,调试器将附加到DLL。
要同时调试两个项目,请将EXE项目加载到IDE中,并确保在项目选项的Debug Source路径中指定了DLL的源文件夹。然后,您可以正常运行EXE项目,在调用DLL函数时进入DLL函数,设置DLL源中的断点等。

1
我发现调试两个项目的一个额外步骤是必要的:将.tds文件(调试器符号)从DLL输出目录复制到应用程序使用的.dll文件所在的位置。 - Josh Kelley
@Josh-Kelley:如果我将“.exe”项目的“工作目录”设置为包含“.dll”和“.tds”文件的路径,则可以在不复制的情况下调试两者。在C++Builder XE中,“工作目录”选项位于“项目选项>调试器”下。 - Pete

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接