What should I do if two libraries provide a function with the same name generating a conflict?
Asked Answered
F

13

132

What should I do if I have two libraries that provide functions with equivalent names?

Fugue answered 24/3, 2009 at 16:47 Comment(5)
are these static libraries or dynamically linked?Humfrey
we need more details... are those names exported? or are they used internally only? Can you change the names?Digamma
They are dynamically linked, both. I can't change the names, since I don't own the libraries.Fugue
Great question. Of course it wouldn't be a problem with these two libraries if all the symbols were prefixed with a unique ID (e.g. vorbis_..., sf_..., sdl_...). This is essentially what C++ does to the symbol names for namespaced functions.Skeie
This is a very interesting question but is sadly too imprecise which is the reason for having too many too broad answers.Piedadpiedmont
C
62
  • If you control one or both: edit one to change the name and recompile Or equivalently see Ben and unknown's answers which will work without access to the source code.
  • If you don't control either of them you can wrap one of them up. That is compile another (statically linked!) library that does nothing except re-export all the symbols of the original except the offending one, which is reached through a wrapper with an alternate name. What a hassle.
  • Added later: Since qeek says he's talking about dynamic libraries, the solutions suggested by Ferruccio and mouviciel are probably best. (I seem to live in long ago days when static linkage was the default. It colors my thinking.)

Apropos the comments: By "export" I mean to make visible to modules linking to the library---equivalent to the extern keyword at file scope. How this is controlled is OS and linker dependent. And it is something I always have to look up.

Crowley answered 24/3, 2009 at 17:2 Comment(9)
That was my first thought as well, but won't you end up with the same collision problem? In the end, the entire project has to link - at compile/link time or at run time - at which time both the offending libraries have to load as-is.Pandich
@unknown: The wrapper must be compiled with static linkage, and should not export the offending symbol. Then you can still dynamically link the wrapper. Edited for more clarity, Thanks.Crowley
If qeek's problem is with ddl's and not static libraries, how is it possible to make a new library with a wrapper? Since, the wrapper library would have to dynamically wrap around a function in the library you don't want to link with in the first place.Challis
@dmckee - what do you mean by "export"?Brigettebrigg
@Neil: Expose. Make visible to modules linking to the library. Equivalent to extern and file level in c.Crowley
@dmckee all functions are extern by default and thus already exposed - I can't see how you can alter this for a precompiled libraryBrigettebrigg
@Neil: It is a function of the linker. You can generally tell your linker to construct library C out of code A and library B without exposing the symbols from B. Or exposing only selected symbols. How to specify it is system dependent.Crowley
i think you can do it with visibility=hidden with gcc/ldDigamma
perhaps someone could provide a simple example of this technique? One exe, two libraries each containing one function with the same name.Brigettebrigg
D
66

It is possible to rename symbols in an object file using objcopy --redefine-sym old=new file (see man objcopy).

Then just call the functions using their new names and link with the new object file.

Doris answered 24/3, 2009 at 17:20 Comment(4)
Nice. This would be trivial to add to a Makefile. If the libraries are ever updated, an objcopy incantation would be much easier to update than some of the other solutions.Afterlife
Don't forget to rename the symbols in the header files as well.Incrassate
^ sed/awk/perl would be useful to automate renaming the symbols in the header, tooRink
Does this work for shared libraries? this answer here says "no".Troubadour
C
62
  • If you control one or both: edit one to change the name and recompile Or equivalently see Ben and unknown's answers which will work without access to the source code.
  • If you don't control either of them you can wrap one of them up. That is compile another (statically linked!) library that does nothing except re-export all the symbols of the original except the offending one, which is reached through a wrapper with an alternate name. What a hassle.
  • Added later: Since qeek says he's talking about dynamic libraries, the solutions suggested by Ferruccio and mouviciel are probably best. (I seem to live in long ago days when static linkage was the default. It colors my thinking.)

Apropos the comments: By "export" I mean to make visible to modules linking to the library---equivalent to the extern keyword at file scope. How this is controlled is OS and linker dependent. And it is something I always have to look up.

Crowley answered 24/3, 2009 at 17:2 Comment(9)
That was my first thought as well, but won't you end up with the same collision problem? In the end, the entire project has to link - at compile/link time or at run time - at which time both the offending libraries have to load as-is.Pandich
@unknown: The wrapper must be compiled with static linkage, and should not export the offending symbol. Then you can still dynamically link the wrapper. Edited for more clarity, Thanks.Crowley
If qeek's problem is with ddl's and not static libraries, how is it possible to make a new library with a wrapper? Since, the wrapper library would have to dynamically wrap around a function in the library you don't want to link with in the first place.Challis
@dmckee - what do you mean by "export"?Brigettebrigg
@Neil: Expose. Make visible to modules linking to the library. Equivalent to extern and file level in c.Crowley
@dmckee all functions are extern by default and thus already exposed - I can't see how you can alter this for a precompiled libraryBrigettebrigg
@Neil: It is a function of the linker. You can generally tell your linker to construct library C out of code A and library B without exposing the symbols from B. Or exposing only selected symbols. How to specify it is system dependent.Crowley
i think you can do it with visibility=hidden with gcc/ldDigamma
perhaps someone could provide a simple example of this technique? One exe, two libraries each containing one function with the same name.Brigettebrigg
S
18

Under Windows, you could use LoadLibrary() to load one of those libraries into memory and then use GetProcAddress() to get the address of each function you need to call and call the functions through a function pointer.

e.g.

HMODULE lib = LoadLibrary("foo.dll");
void *p = GetProcAddress(lib, "bar");
// cast p to the approriate function pointer type (fp) and call it
(*fp)(arg1, arg2...);
FreeLibrary(lib);

would get the address of a function named bar in foo.dll and call it.

I know Unix systems support similar functionality, but I can't think of their names.

Subarid answered 24/3, 2009 at 17:38 Comment(2)
dlopen dlsym, and dlclose. However, the encapsulation on Unix may not be as effective as on Windows.Loyce
An automated solution for LinuxPiedadpiedmont
C
12

If you have .o files there, a good answer here: https://mcmap.net/q/174994/-how-to-deal-with-symbol-collisions-between-statically-linked-libraries

Summary:

  1. objcopy --prefix-symbols=pre_string test.o to rename the symbols in .o file

or

  1. objcopy --redefine-sym old_str=new_str test.o to rename the specific symbol in .o file.
Consolute answered 29/12, 2016 at 8:19 Comment(0)
P
9

Here's a thought. Open one of the offending libraries in a hex editor and change all occurrences of the offending strings to something else. You should then be able to use the new names in all future calls.

UPDATE: I just did it on this end and it seems to work. Of course, I've not tested this thoroughly - it may be no more than a really good way to blow your leg off with a hexedit shotgun.

Pandich answered 24/3, 2009 at 17:12 Comment(3)
actually not a terrible solution. A bit hackish, but all you'd be doing is changing the strings in the symbol table. No real functional harm in that.Plover
You'd probably want to rename the library, as well - lest someone else came along, trying to load the thing again. You'd go from one conflict to dozens or hundreds. =] I love this about stackoverflow: we have a tested answer to a question and it has 3 votes. The first (incomplete) answer: 17. =]Pandich
Renaming opportunities are limited as you'll only be able to make names shorter. Also on Linux you'll have hard time updating ELF hash tables.Piedadpiedmont
I
8

You should not use them together. If I remember correctly, the linker issues an error in such a case.

I didn't try, but a solution may be with dlopen(), dlsym() and dlclose() which allow you to programmatically handle dynamic libraries. If you don't need the two functions at the same time, you could open the first library, use the first function and close the first library before using the second library/function.

Incrassate answered 24/3, 2009 at 17:1 Comment(3)
Thanks. Didn't think about this. Although, I'd like to have both at the same time.Fugue
What if I'd like to use both at the same time?Publication
@QZHua: Other anwsers (e.g., involving symbol renaming) should solve your problem.Incrassate
D
7

Swear? As far as I am aware, there isn't much you can do if you have two libraries that expose link points with the same name and you need to link against both.

Doorjamb answered 24/3, 2009 at 16:54 Comment(2)
Swear is definitely the first step. No doubt about it.Crowley
"there isn't much you can do" - is this still relevant? Other answers provide numerous different solutions.Piedadpiedmont
K
7

Assuming that you use linux you first need to add

#include <dlfcn.h>

Declare function pointer variable in proper context, for example,

int (*alternative_server_init)(int, char **, char **);

Like Ferruccio stated in https://mcmap.net/q/172720/-what-should-i-do-if-two-libraries-provide-a-function-with-the-same-name-generating-a-conflict , load explicitly the library you want to use by executing (pick your favourite flags)

void* dlhandle;
void* sym;

dlhandle = dlopen("/home/jdoe/src/libwhatnot.so.10", RTLD_NOW|RTLD_LOCAL);

Read the address of the function you want to call later

sym = dlsym(dlhandle, "conflicting_server_init");

assign and cast as follows

alternative_server_init = (int (*)(int, char**, char**))sym;

Call in a similar way than the original. Finally, unload by executing

dlclose(dlhandle);
Kilovolt answered 4/7, 2013 at 14:12 Comment(1)
Automation of this approachPiedadpiedmont
E
4

This problem is the reason c++ has namespaces. There's not really a great solution in c for 2 third party libs having the same name.

If it's a dynamic object, you might be able to explicitly load the shared objects (LoadLibrary/dlopen/etc) and call it in that fashion. Alternately, if you don't need both libs at the same time in the same code, you can maybe do something with static linking (if you have the .lib/.a files).

None of these solutions apply to all projects, of course.

Execration answered 24/3, 2009 at 17:2 Comment(1)
Oh yes. For this general question this seems like a good answer. However - namespaces are cool if you compile everything together in the same compiler. Hooray, no name clashes. But if you get a library in binary form, and want to integrate it with another compiler, then - good luck. Name mangling rules in object files are just the first obstackle (extern "C" may help, which undoes the namespaces' efect).Rather
S
3

You should write a wrapper library around one of them. Your wrapper library should expose symbols with unique names, and not expose the symbols of the non-unique names.

Your other option is to rename the function name in the header file, and rename the symbol in the library object archive.

Either way, to use both, it's gonna be a hack job.

Sacred answered 24/3, 2009 at 17:7 Comment(1)
Automation of this solution via Implib.soPiedadpiedmont
S
2

The question is approaching a decade old, but there are new searches all the time...

As already answered, objcopy with the --redefine-sym flag is a good choice in Linux. See, for example, https://linux.die.net/man/1/objcopy for full documentation. It is a little clunky because you are essentially copying the entire library while making changes and every update requires this work to be repeated. But at least it should work.

For Windows, dynamically loading the library is a solution and a permanent one like the dlopen alternative in Linux would be. However both dlopen() and LoadLibrary() add extra code that can be avoided if the only issue is duplicate names. Here the Windows solution is more elegant than the objcopy approach: Just tell the linker that the symbols in a library are known by some other name and use that name. There a few steps to doing it. You need to make a def file and provide the name translation in the EXPORTS section. See https://msdn.microsoft.com/en-us/library/hyx1zcd3.aspx (VS2015, it will eventually get replaced by newer versions) or http://www.digitalmars.com/ctg/ctgDefFiles.html (probably more permanent) for full syntax details of a def file. The process would be to make a def file for one of the libraries then use this def file to build a lib file and then link with that lib file. (For Windows DLLs, lib files only are used for linking, not code execution.) See How to make a .lib file when have a .dll file and a header file for the process of building the lib file. Here the only difference is adding the aliases.

For both Linux and Windows, rename the functions in the headers of the library whose names are being aliased. Another option that should work would be, in files referring to the new names, to #define old_name new_name, #include the headers of the library whose exports are being aliased, and then #undef old_name in the caller. If there are a lot of files using the library, an easier alternative is to make a header or headers that wraps the defines, includes and undefs and then use that header.

Hope this info was helpful!

Sedition answered 1/11, 2017 at 19:59 Comment(0)
P
0

I've never used dlsym, dlopen, dlerror, dlclose, dlvsym, etc., but I'm looking at the man page, and it gives an example of opening libm.so and extracting the cos function. Does dlopen go through the process of looking for collisions? If it doesn't, the OP could just load both libraries manually and assign new names to all the functions his libraries provide.

Pandich answered 24/3, 2009 at 17:6 Comment(0)
B
0

If it's a builtin function. for example, torch has range method(deprecated)and builtin has range method as well.

I was having some issues and all it took was adding __builtins__ before the function name. range() => torch builtins.range()

Bourgeon answered 21/2, 2022 at 11:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.