在同一个C ++项目中链接两个不同版本的protobuf库

时间:2017-04-12 14:12:07

标签: c++ protocol-buffers

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

3 个答案:

答案 0 :(得分:4)

您无法将两个不同版本的libprotobuf链接到同一个程序中。 (这可能在某些操作系统上,但它绝对不会在Linux上运行,其中具有相同名称的声明会相互覆盖。可能可以在Windows或Mac上运行,但是依靠这个可能不是一个好主意。)

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

虽然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()复制到combined1.o就像是static函数一样。当combined1.o,main.c和lib2.c全部链接时,main.c将使用lib2.c中的test(),就像我们想要的那样。

当然,在一个项目中使用同一个库的两个不同版本是一个难以维护的噩梦。你将经常包含错误版本的标题并获得微妙的错误。