1

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?

5
  • Changing names would also break compatibility to other projects... Commented Nov 25, 2024 at 15:14
  • 1
    Rebuild the lib either with additional namespace, or with some renaming? Commented Nov 25, 2024 at 15:15
  • I am writing a wrapper for multiple libraries. This should be solution for your problem. Most probably issue is caused by fact that details of wrapped library are leaking outside of wrapper by its header files. Make sure that public headers of the wrapper do not use any symbols to library it wraps. Using this #define foo lib_foo is wrong since it just hides issue in compilation time (and introduces UB). Also please specify if wrapper is a shared library. Commented Nov 25, 2024 at 15:30
  • "My plan is to change the occurences of foo to lib_foo in the object file of the library". How do you plan to get the object file(s) of the library? Commented Nov 25, 2024 at 15:55
  • I forgot to mention that the libraries I'm wrapping are static libraries. Commented Nov 26, 2024 at 13:51

1 Answer 1

0

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Why does wrapping the libraries in shared libraries work but not in static libraries?
@TomHaswell You don't really "wrap in static library". A static library is just an indexed collection of object files, used in linking step of executable or shared library. All you'd end up with is a static lib that contains the original libs (with symbol conflicts that'll show up at linking) and your wrappers, offloading the same problem to whoever uses that. Note that I'm talking about two separate shared lib wrappers for two offending static libs; they offer more functionality like visible/hidden symbols, avoiding future conflicts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.