4

I have several versions of the same library written in C++. I need to compare them side-by-side. These libraries use the same namespace, function names and take the same parameters.

Are there any methods to control which version of the library I use when I link two or more of them at the same time?

Some Noob Student
  • 14,186
  • 13
  • 65
  • 103
  • 4
    AFAIK, you'd get a linker error complaining about multiple defined symbols. No? – Luchian Grigore Nov 01 '12 at 15:07
  • you can't link two libs with the same symbols, linker will simply refuse to do it. –  Nov 01 '12 at 15:07
  • Well. Glibc has symbol versioning (have a look [at this SO question](http://stackoverflow.com/questions/2856438/how-can-i-link-to-a-specific-glibc-version) for example), an approach which might help you if you can rebuild your libraries to include such metadata. – Rook Nov 01 '12 at 15:10
  • 2
    Don't link against it; `dlopen()`, but be prepared for a maintenance nightmare. – WhozCraig Nov 01 '12 at 15:16
  • Sorry guys, I forgot to say that I was working on the QNX platform, where I could link to 2 of such libraries. The program compiles and can actually run. It just calls one of the libraries. – Some Noob Student Nov 01 '12 at 15:49

1 Answers1

6

You cannot link two libraries with identical symbols and get access to both. However, you can build your own thin wrapper libraries to disambiguate the two versioned libraries:

  • Define an abstract class Wrapper that exercises the functions of the target library using abstract virtual functions
  • Define an implementation of Wrapper in a class called WrapperImpl that calls through to the target library from the virtual methods
  • Define a free-standing method Wrapper *MakeImpl returning new WrapperImpl()
  • Compile WrapperImpl into static libraries several times, linking with different versions of the target library each time. Critical: pass -DWrapperImpl=WrapperImplV1 -DMakeImpl=MakeImplV1 to the compiler, with V1, V2, V3, and so on, for different versions. You should end up with multiple libraries.
  • Link your main tester with these multiple libraries

At this point, your main tester has access to free-standing functions MakeImplV1, MakeImplV2, MakeImplV3 and so on created through renaming MakeImpl through the preprocessor. Use these functions to obtain instances of Wrapper that call through to different versions of the target library.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • I'd be tempted to make the interface for this Wrapper library a single function `Wrapper* GetWrapper()`. Well, actually, `Wrapper* GetWrapperV1()` etc. Then the define replacement only has to happen on a single token in the library -- the name of the GetWrapper function. A pure-virtual Wrapper interface doesn't have to have symbols exported in order to be used by the client under (some?)(most?)(all?) C++ linking architectures (the layout of the pure virtual class is sufficient), and the WrapperImpl is a private implementation detail that you don't export. – Yakk - Adam Nevraumont Nov 01 '12 at 15:37
  • @Yakk That is pretty much what's going on here. The `WrapperImplV1` name is not used - all access is done through the `MakeImplV` functions, the only entry point to his version-specific libraries. – Sergey Kalinichenko Nov 01 '12 at 15:41