如何将 #defines 从 C++ 共享库导出到应用程序

Posted

技术标签:

【中文标题】如何将 #defines 从 C++ 共享库导出到应用程序【英文标题】:How to export a #defines from c++ shared library to application 【发布时间】:2019-02-28 05:14:11 【问题描述】:

我的库是在启用一些#define 的情况下构建的(例如-DUSE_FOO=1),并且USE_FOO 也用于公共头文件。 问题是使用库的应用程序包含公共头文件,因此USE_FOO 出现在应用程序上下文中,并且在应用程序上下文中未定义。

如何根据库中是否启用 USE_FOO 定义将其导出到应用程序?

例如

include/public/foo.h
lib/libfoo.so   --> foo.cc

in foo.h contain code as  
#if defined (USE_FOO)
#define SIZE 5
#else
#define SIZE 10
#endif

foo.cc
#include "foo.h"
int getSizeFromLib()

 return SIZE;

libfoo.so 源文件包含foo.h 并通过在编译时配置USE_FOO 构建。

现在,应用程序通过包含 public/foo.h 来使用 libfoo 库,并使用他自己的构建配置来构建应用程序。但问题是应用程序不知道USE_FOO 在应用程序端将始终未定义。所以SIZE 在应用程序中是 10,但在库中是 5

我希望 USE_FOO 根据是否为 ​​libfoo.so 定义而导出到应用程序。即如果libfoo.so 是用USE_FOO=1 构建的,应用程序也应该看到USE_FOO=1,反之亦然

如果无法以预定义的方式进行,那么任何解决此问题的技巧都会受到欢迎。

【问题讨论】:

共享库没有类似于#define 的内容。您需要自己处理编译标志。 【参考方案1】:

在 Linux 世界中,此任务由 pkgconfig 工具解决。基本上除了二进制文件和头文件之外,您的库还附带一个 .pc 文件,看起来像

prefix=/usr/local
exec_prefix=$prefix
includedir=$prefix/include
libdir=$exec_prefix/lib

Name: foo
Description: The foo library
Version: 1.0.0
Cflags: -I$includedir/foo USE_FOO=1
Libs: -L$libdir -lfoo

这个文件安装到/usr/lib/pkgconfig,客户端应该通过从Makefile调用pkg-config来查询正确的CFLAGS

CFLAGS = -g -Wall -Wextra $(pkg-config --cflags)

更多详情,请查看guide。

唯一的可移植解决方案是添加一个自动生成 foo-config.h 标头,该标头将包含在所有库公共标头中,并将定义所有特定于版本的定义(如USE_FOO)。这当然只适用于实际包含库头文件的源文件。

【讨论】:

【参考方案2】:

无法将预处理器定义从库“导出”到应用程序。两者都必须使用兼容的标志进行编译,例如:

CFLAGS=-DUSE_FOO=1
gcc $CFLAGS --shared -o lib/libfoo.so foo.cc
gcc $CFLAGS lib/libfoo.so app.c

【讨论】:

“无法从库中导出预处理器定义”——至少在 Linux pkg-config 上会这样做。

以上是关于如何将 #defines 从 C++ 共享库导出到应用程序的主要内容,如果未能解决你的问题,请参考以下文章

WebAssembly:将命名空间从 C++ 库导出到 JavaScript

在 C++ 中创建 Windows 共享库时如何实现接口隔离

如何使共享库符号强大?

从 Linux 动态库/Linux 控制台应用程序导出/导入 C++ 函数 | Visual Studio Linux 项目

如何重新导出 CLR c++ 静态库

是否可以从将引用作为参数的 rust dll 导出函数