Link two different version of protobuf library in

2019-07-04 01:00发布

问题:

can I use both protobuf 2.6 and 3.0 libs in the same c++ project and link them together?

回答1:

You cannot link two different versions of libprotobuf into the same program. (It may be possible on some OS's, but it definitely won't work on Linux, where the declarations with the same names would overwrite each other. It may be possible to make work on Windows or Mac, but it's probably not a good idea to rely on this.)

However, you don't need to do this. libprotobuf 3.x supports both "proto3" and "proto2" syntax. As long as you can rebuild your code from source (including regenerating the .pb.h and .pb.cc files), you should be able to rebuild everything using version 3.x, even if some of the proto files use proto2-exclusive features.



回答2:

While C++ might not support the concept of linking multiple versions of the same symbol into a single object, it can still be done. Executable formats like ELF or PE support many things that are not part of the C++ standard. Using symbol visibility and partial linking, one can have code that uses two different copies of the same symbols.

I'm guessing you want to link to two different already compiled protobuf shared libraries. That won't work. You'll have to statically link at least one protobuf and compile it yourself.

It would look something like this:

// 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(); }

We want usetest() from uselib1.c to call the version of test() that's in lib1.c, while main() should call the version that's in lib2.c. If we just link all these together, it doesn't work:

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

You can't have multiple copies if test(). But what we can do is partially link just uselib1 and lib1, which works since there is only one test() with just those two objects. Then the symbols from lib1 are localized so that nothing else using the combined uselib1+lib1 will see the lib1 symbols.

$ 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

When compiling lib1, I use -fvisibility=hidden to mark all the symbols in lib1 as hidden. This would make a difference if it were a shared library. As an object (or static lib) they can still be used by other code, and they are used when "ld -r" partially links lib1.o and uselib1.o into combined1.o. Then objcopy localizes all the hidden symbols. This has the effect of making the copy of test() inside combined1.o act like it was a static function. When combined1.o, main.c, and lib2.c are all linked, main.c will use test() from lib2.c like we want.

Of course, using two different versions of the same library in one project is a nightmare to maintain. You'll constantly be including the wrong version's headers and getting subtle bugs.



回答3:

I'm not familiar with the library but in general no unless each library is 100% contained in it's own unique namespace. Otherwise there will be a name clashes with each class, function, etc.