我可以在同一个 C++ 项目中同时使用 protobuf 2.6 和 3.0 库并将它们链接在一起吗?
您不能将两个不同版本的 libprotobuf 链接到同一个程序中。(在某些操作系统上可能可行,但在 Linux 上肯定行不通,在 Linux 上,具有相同名称的声明会相互覆盖。可能可以在 Windows 或 Mac 上工作,但这可能不是一个好主意依靠这个。)
但是,您不需要这样做。libprotobuf 3.x 支持“proto3”和“proto2”语法。只要您可以从源代码重建代码(包括重新生成 .pb.h 和 .pb.cc 文件),您就应该能够使用 3.x 版重建所有内容,即使某些 proto 文件使用 proto2-exclusive特征。
虽然 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(); }
Run Code Online (Sandbox Code Playgroud)
我们希望usetest()
从 uselib1.c 调用test()
lib1.c 中的版本,而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'
Run Code Online (Sandbox Code Playgroud)
如果 ,则您不能拥有多个副本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
Run Code Online (Sandbox Code Playgroud)
编译lib1时,我将-fvisibility=hidden
lib1中的所有符号标记为隐藏。如果它是一个共享库,这将会有所不同。作为对象(或静态库),它们仍然可以被其他代码使用,并且当“ld -r”将 lib1.o 和 uselib1.o 部分链接到组合1.o 时使用它们。然后 objcopy 本地化所有隐藏的符号。这具有使combined1.o内部的副本test()
表现得像一个static
函数的效果。当combined1.o、main.c和lib2.c全部链接时,main.c将test()
像我们想要的那样使用lib2.c中的内容。
当然,在一个项目中使用同一库的两个不同版本对于维护来说是一场噩梦。您将不断地包含错误版本的标头并遇到细微的错误。
归档时间: |
|
查看次数: |
2898 次 |
最近记录: |