0

I am trying to link same application two different versions of the same library. Lets call the library libOld and libNew. libNew has a new method (lets call it newMethod()) which libOld does not.

When my application tries to call the newMethod() which is not in libOld the linker obviously fails. Is it possible to get around this problem somehow so that I can link to newMethod() only if it is available? That is, if the application is linked with libNew and not libOld.

The library I'm trying to link with is built in c++ and I cannot delay or dynamically load it since it contains exported static data objects and it does not contain any extern "C" factory classes for constructing c++ objects which could help out with memory management.

Toolchain Update

The application is build in Windows for Windows CE 5.0 running on an ARM processor (if that matters). The library I am trying to use is closed source. The application uses the qt framework.

MikaelHalen
  • 5,772
  • 1
  • 18
  • 16
  • You probably shouldn't break interfaces that way if you want to keep backwards compatibility. – πάντα ῥεῖ Oct 11 '16 at 11:00
  • 2
    So what do you expect the call to newMethod do if it's not available? – Nikolai Oct 11 '16 at 11:02
  • 2
    You cannot wave a magic wand and make a function go away. Your application calls `newMethod()`. `newMethod()` obviously does something that your application needs, unless your application has a habit of calling random functions for no particular reason. So it has to call `newMethod()`. The End. – Sam Varshavchik Oct 11 '16 at 11:02
  • If you can't decide the version at compile time, you could perhaps dynamically load the code which calls `newMethod()` (and then loading will fail with *libOld*, and then you do something else, like load another piece of code which works correctly with *libOld*. – hyde Oct 11 '16 at 11:15
  • It depends on what toolchain and OS you are using, but typically you would use *weak linking* when you build, and then you would test for the existence of a given routine at run-time before trying to call it. This of course assumes dynamic/shared libraries (DLLs in Microsoft parlance). – Paul R Oct 11 '16 at 11:30
  • @SamVarshavchik my application could change behavior based on what functions are available so if newMethod() is not avaialble I could skip a feature that might require newMethod(). – MikaelHalen Oct 12 '16 at 08:24
  • @hyde that could work. The issue I've hade with loading the function pointer dynamically is that it is attached to a c++ object. That c++ object has a constructor function pointer available but now extern "C" factory funtions. So I cannot allocate the correct amount of memory for that object. It would be great if I could connect the functionpointer to the c++ object somehow but I've never heard anyone do something like that. – MikaelHalen Oct 12 '16 at 08:28
  • @PaulR unfortunately the library isn't built to be loaded dynamically. It has exported static functions and that in turn makes the linker fail. – MikaelHalen Oct 12 '16 at 08:30
  • @Nikolai if newMethod() is not available I could avoid using a feature that requires that function. – MikaelHalen Oct 12 '16 at 08:31
  • 1
    "cannot delay or dynamically load", that's incorrect. But it does need a bit of work. – Cheers and hth. - Alf Oct 12 '16 at 08:49
  • 1
    Operating system / tool chain would be useful information to add to the question. – hyde Oct 12 '16 at 15:29
  • @hyde Updated the question with tool chain and operating system – MikaelHalen Oct 13 '16 at 05:56

3 Answers3

2

The usual solution is to add a weak symbol newMethod() to your executable. Since libNew offers a strong symbol newMethod, this overrides the weak symbol. When you link with lidOld, the weak symbol is the only symbol and will be used.

Weak symbols are common but not Standard. Check your compiler toolchain.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • I think this might just be a working solution. I did try weak linking before but the compiler did not quite like the #pragma flags i put in. Could perhaps depend on the compiler toolchain, as you mentioned. I believe this is the correct answer and I'll accept it as soon as I have tested it again. – MikaelHalen Oct 13 '16 at 06:08
  • For future reference: I found a weak linking stack overflow question answered here: http://stackoverflow.com/questions/2290587/gcc-style-weak-linking-in-visual-studio – MikaelHalen Oct 13 '16 at 06:09
1

Your problem, if I understand it correctly, is not something you can solve in an elegant way, because it is not a problem which is "meant" to be directly solved. You are "meant" to build an application against a specific library version (it may work against other versions, if they are specifically made binary compatible, but that is rare because it requires extra effort in design and testing).

So, if you need to support multiple conflicting library versions, you provide multiple versions of application binary. Simple as that.

If you need to provide a single application installer package, you can create a separate launcher app, which somehow detects which actual application binary should be executed (this can be just a .BAT/shell script). Detection can be as simple as trying to launch one binary, and if it fails with the specific error code (caused by DLL loading problem), then you launch the other binary.

hyde
  • 60,639
  • 21
  • 115
  • 176
0

One would expect that the library offers some mechanism to get version... the question is how is that done.

If it's a #define with the version number, then you can surround your newMethod() with #if's.

If you have functions that return your version, or your version isn't available at all, now would be a good time to introduce them, but you'll have to add #ifdef to support.

UKMonkey
  • 6,941
  • 3
  • 21
  • 30
  • The issue with using #if:s is that it would require building two different versions of the application. Our deployment system is a bit tough to work with and we cannot deploy specific version of our software based on the library versions available. Instead we need to solve the problem at run-time or link-time. – MikaelHalen Oct 12 '16 at 08:35
  • I think you need to work out if you're using static libraries or dynamic libraries, because you're talking as though your library is both. If it's static, there's 1 version being used, and it's part of the binary. It can't be changed and you know at compile time what version it is. If it's dynamic, you call a function to get the version and then branch based on that if required. – UKMonkey Oct 12 '16 at 08:41
  • You might be correct in that I have described the issue incorrectly or I might have a hard time understanding exactly how it is linked. However, the application is linked at startup, and if I try to build with a delayed linking the compiler complains about exported static functions, at build time. This indicates that the application is linked once when compiling, and once at startup. Not entirely sure why that is, so I gather I will need to read into it. – MikaelHalen Oct 13 '16 at 05:50