c++ - 外部符号的可见性和可移植性

标签 c++ linker extern

我正在尝试制作一个特殊的 .cpp 文件,它有一个 const char* version,包含包版本,然后在编译后链接到库和可执行文件包裹。库和可执行文件将其引用为 extern 符号,如下所示:

版本.cpp

const char* version=VERSION_STRING;

版本.h

extern const char* version;

库和可执行文件中的代码有

#include "version.h"

现在,问题是可执行文件必须询问库版本的库,但由于符号是 extern,其实例名称冲突,结果是即使库版本是不同,可执行文件认为它是相同的。

我尝试使用 -fvisibility=hidden gcc 选项或相应的 __attribute__ 来避免这种情况(事实上,它在 glib 中的包装器:G_GNUC_INTERNAL),它可以工作,但令我困扰的是它根本不可移植,也就是说,我不确定这在 Windows 中如何工作。

所以问题是:在不牺牲可移植性的情况下,有什么更简洁的方法可以在更改版本时避免过多的重新编译并且仍然没有外部可见(给定二进制文件之外)的版本符号?

最佳答案

或者:

  • 可执行文件必须向库“询问”版本(在这种情况下,符号不是应该是extern,库应该只提供一些const char *lib_get_version() 功能)
  • 或者符号应该是外部的并且对可执行文件直接可见,在这种情况下它应该由库提供。也就是说,version.cpp 将链接到库而不是可执行文件,因此库将符号提供给最终的可执行文件。

第一个选项可能是最简单和最便携的。


对于两个版本,可能不一样:

  1. 创建两个单独的文件,比如 lib_version.cppbin_version.cpp,导出 const char *get_lib_version()const char *get_bin_version() 分别
  2. 将第一个cpp文件编译到lib中,将第二个cpp文件编译到bin中。
  3. 如果版本控制是相同的,比如 bin 和 lib 具有不同版本的某些 API,则创建两个 cpp 文件使用的私有(private) header

    // header_impl.h
    #define VERSION_STRING "1.2.3"
    
    // lib_version.h
    const char *get_lib_version();
    
    // lib_version.cpp (linked only in lib)
    #include <version_impl.h>
    const char *get_lib_version() { return VERSION_STRING; }
    
    // bin_version.h
    const char *get_bin_version();
    
    // bin_version.cpp (linked only in bin)
    #include <version_impl.h>
    const char *get_bin_version() { return VERSION_STRING; }
    

    现在,lib 和 bin 都包含版本的快照,来自 version_impl header ,在它们被编译时。您可以在没有链接器冲突的情况下获得这两个值。

关于c++ - 外部符号的可见性和可移植性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21572184/

相关文章:

c - GDB进入动态链接器(ld.so)代码

c++ - 理解 C++ 中的 extern

c++ - 在 C++ 中访问在一个文件中声明的变量到另一个文件中。 (外部关键字用法)

c++ - 为什么要使外部变量成为引用?

c++ - 如何在 C++ 中正确地将一个类的头文件包含在另一个类的头文件中?

c++ - 具有折叠表达式的模板会创建不需要的参数拷贝

gcc - GCC 中的 OpenSSL 链接选项 -lssl 和 -lcrypto

c++ - 使用包含另一个静态库的静态库时出现 LNK4006、LNK4221 警告

C++ vector,这段代码是什么意思?

c++ - 如何确保在 C++ 编译期间将参数视为常量?