【问题标题】:Link two different version of protobuf library in the same C++ project在同一个 C++ 项目中链接两个不同版本的 protobuf 库
【发布时间】:2017-04-12 14:12:06
【问题描述】:

我可以在同一个 c++ 项目中同时使用 protobuf 2.6 和 3.0 库并将它们链接在一起吗?

【问题讨论】:

  • 除非它们都 100% 包含在自己的命名空间中。

标签: c++ protocol-buffers


【解决方案1】:

您不能将两个不同版本的 libprotobuf 链接到同一个程序中。 (在某些操作系统上可能可行,但在 Linux 上肯定行不通,在 Linux 上,同名的声明会相互覆盖。在 Windows 或 Mac 上可能可行,但这可能不是一个好主意依靠这个。)

但是,您不需要这样做。 libprotobuf 3.x 支持“proto3”和“proto2”语法。只要您可以从源代码重建代码(包括重新生成 .pb.h 和 .pb.cc 文件),您应该能够使用 3.x 版本重建所有内容,即使某些 proto 文件使用 proto2-exclusive功能。

【讨论】:

    【解决方案2】:

    虽然 C++ 可能不支持将同一符号的多个版本链接到单个对象的概念,但仍然可以这样做。 ELF 或 PE 等可执行格式支持许多不属于 C++ 标准的内容。使用符号可见性和部分链接,可以使代码使用相同符号的两个不同副本。

    我猜你想链接到两个不同的已编译的 protobuf 共享库。那是行不通的。您必须静态链接至少一个 protobuf 并自行编译。

    看起来像这样:

    // lib1.c
    void test(void) { printf("test version 1\n"); }
    
    // lib2.c
    void test(void) { printf("test version 2\n"); }
    
    // uselib1.c
    void test(void);
    void usetest(void) { test(); }
    
    // main.c
    void test(void);
    void usetest(void);
    int main(void) { usetest(); test(); }
    

    我们希望uselib1.c 中的usetest() 调用lib1.c 中的test() 版本,而main() 应该调用lib2.c 中的版本。如果我们只是将所有这些链接在一起,那是行不通的:

    $ gcc uselib1.c lib1.c main.c lib2.c
    /tmp/ccqQhm5c.o: In function `test':
    lib2.c:(.text+0x0): multiple definition of `test'
    

    test() 不能有多个副本。但是我们可以做的是部分链接 uselib1 和 lib1,因为只有一个 test() 与这两个对象。然后来自 lib1 的符号被本地化,这样使用组合 uselib1+lib1 的其他任何东西都不会看到 lib1 符号。

    $ gcc -c -fvisibility=hidden lib1.c
    $ gcc -c uselib1.c 
    $ ld -r uselib1.o lib1.o -o combined1.o
    $ objcopy --localize-hidden combined1.o 
    $ gcc main.c lib2.c combined1.o 
    $ ./a.out
    test version 1
    test version 2
    

    在编译 lib1 时,我使用-fvisibility=hidden 将 lib1 中的所有符号标记为隐藏。如果它是共享库,这将有所不同。作为一个对象(或静态库),它们仍然可以被其他代码使用,并且当“ld -r”将lib1.o和uselib1.o部分链接到combined1.o时使用它们。然后 objcopy 本地化所有隐藏的符号。这具有使 test() 在 combine1.o 中的副本像 static 函数一样的效果。当combined1.o、main.c 和lib2.c 全部链接时,main.c 将使用lib2.c 中的test()

    当然,在一个项目中使用同一个库的两个不同版本是一场噩梦。你会不断地包含错误版本的标题并得到一些细微的错误。

    【讨论】:

      【解决方案3】:

      我不熟悉该库,但通常不熟悉,除非每个库都 100% 包含在它自己独特的命名空间中。否则每个类、函数等都会有名称冲突。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-11
        • 2019-08-11
        • 1970-01-01
        • 2015-10-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多