两个可以相互扩展的库
Two libraries which can expand each other
所以我正在为我和我的团队开发模块化 C++ 库。这是我的情况:
我有一个库 A
,其中包含一个复杂的存储控件 class a
。我还有一个库 B
,它类似于包含特殊响应的复杂协议的接口。现在,我想在 class a 中有一个函数,它可以使用 B
。这对使用 A
和 B
的程序 X
很有帮助。但是也有程序Y
,它只会使用A
而不是复杂的库B
。
如何在 C++ 中获得此行为?我是否需要宏、符号或是否有其他方法可以轻松实现这一点,这样我就不需要在程序中包含额外的文件?哪种类型的图书馆更好?
这在系统库中很常见,可以在(库)编译时选择可选功能。使用这种方法,您将拥有一个或多个 #define
预处理器宏来保护可选功能。因此,在库 A 中:
#ifdef USE_LIBRARY_B
#include <b/foo.h>
int A_optional_feature_using_B(void) { ... }
#endif
// rest of library A follows
在编译时,您可以定义或不定义 USE_LIBRARY_B
(当然还要添加任何必要的链接器标志)。例如,在 UNIX-like 平台上使用 gcc
:
$ gcc ... -DUSE_LIBRARY_B ...
最常见的是,类似 autoconf
的东西用于 UNIX 环境,为 end-user 提供一种简单的方法来 select 可选功能。因此,您可能会看到:
me@pc:library_a$ ./configure --with-library-b
有关如何进行类似设置的信息,请参阅 autoconf
文档。
在 Windows 上,您可以做类似的事情(例如,在 Visual Studio 中,使用不同的 Project/Solution 配置来定义适当的宏)。
以上内容仅让您compile-time 控制额外的功能。要允许在 runtime 进行选择,以便库可以使用 B(如果存在),您将需要使用运行时动态链接。这是高度platform-specific。在 Linux 上,使用 libdl
. On Windows, use LoadLibrary()
和朋友。在这里你将不得不做很多额外的编码来查找和加载可选库(如果存在)和 return 适当的错误代码/异常(如果不存在)并且调用需要可选库的函数。
如果这一切听起来像是背部疼痛,那么您是对的,确实如此。如果有任何合理的方法来调整你的策略,这样你就不必这样做,你会过得更好。但对于某些用例, 是必要且适当的,如果您的情况如此,那么我希望以上内容能为您提供一些起点,祝您好运。
所以我正在为我和我的团队开发模块化 C++ 库。这是我的情况:
我有一个库 A
,其中包含一个复杂的存储控件 class a
。我还有一个库 B
,它类似于包含特殊响应的复杂协议的接口。现在,我想在 class a 中有一个函数,它可以使用 B
。这对使用 A
和 B
的程序 X
很有帮助。但是也有程序Y
,它只会使用A
而不是复杂的库B
。
如何在 C++ 中获得此行为?我是否需要宏、符号或是否有其他方法可以轻松实现这一点,这样我就不需要在程序中包含额外的文件?哪种类型的图书馆更好?
这在系统库中很常见,可以在(库)编译时选择可选功能。使用这种方法,您将拥有一个或多个 #define
预处理器宏来保护可选功能。因此,在库 A 中:
#ifdef USE_LIBRARY_B
#include <b/foo.h>
int A_optional_feature_using_B(void) { ... }
#endif
// rest of library A follows
在编译时,您可以定义或不定义 USE_LIBRARY_B
(当然还要添加任何必要的链接器标志)。例如,在 UNIX-like 平台上使用 gcc
:
$ gcc ... -DUSE_LIBRARY_B ...
最常见的是,类似 autoconf
的东西用于 UNIX 环境,为 end-user 提供一种简单的方法来 select 可选功能。因此,您可能会看到:
me@pc:library_a$ ./configure --with-library-b
有关如何进行类似设置的信息,请参阅 autoconf
文档。
在 Windows 上,您可以做类似的事情(例如,在 Visual Studio 中,使用不同的 Project/Solution 配置来定义适当的宏)。
以上内容仅让您compile-time 控制额外的功能。要允许在 runtime 进行选择,以便库可以使用 B(如果存在),您将需要使用运行时动态链接。这是高度platform-specific。在 Linux 上,使用 libdl
. On Windows, use LoadLibrary()
和朋友。在这里你将不得不做很多额外的编码来查找和加载可选库(如果存在)和 return 适当的错误代码/异常(如果不存在)并且调用需要可选库的函数。
如果这一切听起来像是背部疼痛,那么您是对的,确实如此。如果有任何合理的方法来调整你的策略,这样你就不必这样做,你会过得更好。但对于某些用例, 是必要且适当的,如果您的情况如此,那么我希望以上内容能为您提供一些起点,祝您好运。