Reputation: 11
I am writing a wrapper for multiple static libraries that are implementing similar functionality. Two of those libraries share the same class names and (because of their age) don't make use of namespaces.
This lead to compiler errors in my program because the class has two different implementations.
I fixed the compiler issues by redefining the class name using #define for one of the libraries. Which looks like this:
#define foo lib_foo
#include "lib.h"
#undef foo
At first, this seemed to work. But now, when assigning a value to an instance of lib_foo, I get this error:
undefined reference to `lib_foo::operator=(lib_foo const&)'
The class seems to override the assignment operator (and obviously has other functions which take a lib_foo
as an input parameter) and the linker can't find the corresponding implementations for these functions, because they are defined in a .cpp file which doesn't get the #define treatment.
I can't introduce namespaces to the original lib (it's not my lib and it would break compatibility to other projects).
My plan is to change the occurences of foo
to lib_foo
in the object file of the library, but I don't know how to do this.
I found this post which deals with this kind of problem but for c funtions and in a much simpler manner.
Does someone have experience with this? Or is there an easier way to handle this problem?
Upvotes: 1
Views: 62
Reputation: 349
Write a separate shared library wrapper for each of the external libraries, where you give distinguishable names. You can also hide/strip all symbols other than your wrapper's. This is a clean way that doesn't require you to modify existing libraries. It only doesn't work if you don't want to or can't use shared libraries, e.g. in embedded bare metal context.
You can still rename mangled symbols in a static library, in a similar way to the answer you found. Just use objcopy
with --redefine-sym
option. The worst part of that is needing to get mangled symbols right. Example:
lib1.h
class foo {
int value;
public:
foo(int value_);
foo & operator=(foo const & foo_);
};
lib1.cpp
#include "lib1.h"
foo::foo(int value_) : value{value_} {}
foo & foo::operator=(foo const & foo_) {
value = foo_.value;
return *this;
}
lib2.h
class foo {
float value;
public:
foo(float value_);
foo & operator=(foo const & foo_);
};
lib2.cpp
#include "lib2.h"
foo::foo(float value_) : value{value_} {}
foo & foo::operator=(foo const & foo_) {
value = foo_.value;
return *this;
}
main.cpp
#include <cstdio>
#define foo lib1_foo
#include "lib1.h"
#undef foo
#define foo lib2_foo
#include "lib2.h"
#undef foo
int main() {
lib1_foo int_object(1);
lib2_foo float_object(1.5);
lib1_foo other_int_object(-1);
lib2_foo other_float_object(-1.5);
other_int_object = int_object;
other_float_object = float_object;
}
Simulate the process of building and using the libraries:
$ g++ -o lib1.cpp.o -c lib1.cpp -I$(pwd)
$ g++ -o lib2.cpp.o -c lib2.cpp -I$(pwd)
$ ar qc lib1.o lib1.cpp.o
$ ar qc lib2.o lib2.cpp.o
$ g++ main.cpp lib1.o lib2.o -I$(pwd)
Undefined references appear at link stage in the final command. We need to know new mangled symbols with which to replace current mangled symbols, so objdump -t lib1.o
tells us we have symbols _ZN3fooC2Ei
, _ZN3fooC1Ei
and _ZN3fooaSERKS_
, so replace each 3foo
substring with 8lib1_foo
. Same for lib2
. Alternatively, we could compile object file of main.cpp
and look at missing symbol names there.
$ objcopy --redefine-sym _ZN3fooC1Ei=_ZN8lib1_fooC1Ei --redefine-sym _ZN3fooC2Ei=_ZN8lib1_fooC2Ei --redefine-sym _ZN3fooaSERKS_=_ZN8lib1_fooaSERKS_ lib1.o lib1c.o
$ objcopy --redefine-sym _ZN3fooC1Ef=_ZN8lib2_fooC1Ef --redefine-sym _ZN3fooC2Ef=_ZN8lib2_fooC2Ef --redefine-sym _ZN3fooaSERKS_=_ZN8lib2_fooaSERKS_ lib2.o lib2c.o
$ g++ main.cpp lib1c.o lib2c.o -I$(pwd)
No linking errors this time. If there are many symbols to redefine, we can use --redefine-syms
with a file instead. I don't recommend any approach that modifies existing libraries and headers since it's easy to miss some runtime fail introduced by renaming, but if you really need it, it's possible like this.
Upvotes: 0