外部符号和便携性的可见性

时间:2014-02-05 08:35:24

标签: c++ linker extern

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

version.cpp

const char* version=VERSION_STRING;

version.h中

extern const char* version;

库和可执行文件中的代码

#include "version.h"

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

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

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

2 个答案:

答案 0 :(得分:2)

或者:

  • 可执行文件必须“询问”库的版本(在这种情况下,符号应该是extern,并且您的库应该只提供一些const char *lib_get_version()函数)
  • 或符号应该是extern并且可以直接显示在可执行文件中,在这种情况下它应该由库提供。也就是说,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文件使用的私有头

    // 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都包含版本的shapshot,来自version_impl头文件,在编译时。您可以在没有链接器冲突的情况下获取这两个值。

答案 1 :(得分:0)

在交叉编译代码中解决这样的版本问题通常你有以下方法:

- both the library and app have their own .cpp file.
 - the library includes a getLibVersion() function in the API to get the library version.
 - the app has access to this getLibVersion() and either calls it to build a larger string containing both lib and app string(eg. 16bit for app, 16 bit for lib giving a 32 bit string) or provides a wrapper for this function which can be called from the app API.

底线 - 有两个version.cpp文件(lib + app) - 如果lib版本发生变化,您必须重建应用程序 - 并且应用程序在其API中提供功能以单独获取版本或连接。

希望这会有所帮助。