What should I do if two libraries provide a functi

2019-01-03 01:33发布

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

12条回答
Rolldiameter
2楼-- · 2019-01-03 02:08
  • 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.

查看更多
聊天终结者
3楼-- · 2019-01-03 02:11

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://stackoverflow.com/a/678453/1635364 , 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);
查看更多
一纸荒年 Trace。
4楼-- · 2019-01-03 02:11

If you have .o files there, a good answer here: https://stackoverflow.com/a/6940389/4705766

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.
查看更多
Root(大扎)
5楼-- · 2019-01-03 02:17

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.

查看更多
时光不老,我们不散
6楼-- · 2019-01-03 02:19

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.

查看更多
贪生不怕死
7楼-- · 2019-01-03 02:20

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!

查看更多
登录 后发表回答