如果两个库提供同名函数产生冲突怎么办?

发布于 2024-07-15 03:42:51 字数 33 浏览 7 评论 0原文

如果我有两个提供具有相同名称的函数的库,我该怎么办?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

○闲身 2024-07-22 03:42:51

可以使用 objcopy --redefine-sym old=new file 重命名目标文件中的符号(请参阅 man objcopy)。

然后只需使用新名称调用函数并链接到新的目标文件即可。

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.

孤独患者 2024-07-22 03:42:51
  • 如果您控制其中之一或两者:编辑其中一个以更改名称并重新编译或者等效地参见 Ben未知的答案,无需访问即可工作到源代码。
  • 如果您无法控制其中任何一个,您可以将其中一个包裹起来。 这是编译另一个静态链接!)库,除了重新导出原始符号之外的所有符号(除了有问题的符号之外)什么都不做,这是通过带有备用名称。 真麻烦啊。
  • 稍后添加:由于qeek说他正在谈论动态库,因此Ferrucciomouviciel 可能是最好的。 (我似乎生活在很久以前,静态链接是默认的。它改变了我的想法。)

关于评论:通过“导出”,我的意思是使链接到库的模块可见——相当于 文件范围内的 extern 关键字。 如何控制它取决于操作系统和链接器。 这是我总是必须查找的东西。

  • 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.

樱花落人离去 2024-07-22 03:42:51

在 Windows 下,您可以使用 LoadLibrary() 来将这些库之一加载到内存中,然后使用 GetProcAddress()< /a> 获取需要调用的每个函数的地址,并通过函数指针来调用函数。

例如

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);

将获取 foo.dll 中名为 bar 的函数的地址并调用它。

我知道 Unix 系统支持类似的功能,但我想不起它们的名字。

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.

甜味超标? 2024-07-22 03:42:51

如果您在那里有 .o 文件,这里有一个很好的答案:https://stackoverflow.com/a/6940389/4705766

摘要:

  1. objcopy --prefix-symbols=pre_string test.o 重命名 .o 文件中的符号

  1. objcopy --redefine-sym old_str=new_str test.o 重命名.o 文件中的特定符号。

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.
冰葑 2024-07-22 03:42:51

这是一个想法。 在十六进制编辑器中打开有问题的库之一,并将所有出现的有问题的字符串更改为其他内容。 然后您应该能够在以后的所有呼叫中使用新名称。

更新:我刚刚在这方面做到了,它似乎有效。当然,我还没有彻底测试过这一点 - 这可能只不过是用一个非常好的方法来炸掉你的腿十六进制编辑霰弹枪。

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.

寄离 2024-07-22 03:42:51

您不应该一起使用它们。 如果我没记错的话,链接器在这种情况下会发出错误。

我没有尝试,但解决方案可能是使用 dlopen()dlsym()dlclose(),它们允许您以编程方式处理动态库。 如果您不需要同时使用这两个函数,您可以打开第一个库,使用第一个函数并在使用第二个库/函数之前关闭第一个库。

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.

淡淡離愁欲言轉身 2024-07-22 03:42:51

发誓? 据我所知,如果您有两个公开具有相同名称的链接点的库并且您需要链接这两个库,那么您无能为力。

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.

素衣风尘叹 2024-07-22 03:42:51

假设您使用 Linux,您首先需要在适当的上下文中添加

#include <dlfcn.h>

Declare 函数指针变量,例如,

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

https://stackoverflow 中所述的 Ferruccio .com/a/678453/1635364
通过执行显式加载您想要使用的库(选择您最喜欢的标志)

void* dlhandle;
void* sym;

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

读取您想要稍后调用的函数的地址

sym = dlsym(dlhandle, "conflicting_server_init");

分配并转换如下

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

以与原始方式类似的方式调用。 最后执行卸载

dlclose(dlhandle);

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);
脸赞 2024-07-22 03:42:51

这个问题就是 c++ 有命名空间的原因。 对于两个具有相同名称的第三方库,c 中实际上没有一个很好的解决方案。

如果它是动态对象,您可能能够显式加载共享对象(LoadLibrary/dlopen/等)并以这种方式调用它。 或者,如果您不需要在同一代码中同时使用两个库,则可以使用静态链接执行某些操作(如果您有 .lib/.a 文件)。

当然,这些解决方案并不适用于所有项目。

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.

多情癖 2024-07-22 03:42:51

您应该围绕其中之一编写一个包装器库。
您的包装器库应该公开具有唯一名称的符号,而不是公开非唯一名称的符号。

您的另一个选择是重命名头文件中的函数名称,并重命名库对象存档中的符号。

不管怎样,要同时使用这两种方法,这将是一项艰巨的工作。

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.

青衫儰鉨ミ守葔 2024-07-22 03:42:51

这个问题已经有近十年的历史了,但是一直有新的搜索......

正如已经回答的那样,带有 --redefine-sym 标志的 objcopy 在 Linux 中是一个不错的选择。 例如,请参见 https://linux.die.net/man/1/objcopy 获取完整文档。 它有点笨重,因为您实际上是在进行更改时复制整个库,并且每次更新都需要重复这项工作。 但至少它应该有效。

对于 Windows,动态加载库是一种解决方案,并且是永久性的解决方案,就像 Linux 中的 dlopen 替代方案一样。 然而,dlopen() 和 LoadLibrary() 都添加了额外的代码,如果唯一的问题是重复的名称,则可以避免这些代码。 这里,Windows 解决方案比 objcopy 方法更优雅:只需告诉链接器库中的符号有其他名称,并使用该名称即可。 有几个步骤可以做到这一点。 您需要创建一个 def 文件并在 EXPORTS 部分中提供名称翻译。 请参阅 https://msdn.microsoft.com/en-us/library/hyx1zcd3 .aspx (VS2015,它最终会被更新的版本取代)或 http:// /www.digitalmars.com/ctg/ctgDefFiles.html(可能更永久)了解 def 文件的完整语法详细信息。 该过程是为其中一个库创建一个 def 文件,然后使用该 def 文件构建一个 lib 文件,然后与该 lib 文件链接。 (对于 Windows DLL,lib 文件仅用于链接,而不用于代码执行。)请参阅 当有.dll文件和头文件时如何制作.lib文件用于构建lib文件的过程。 这里唯一的区别是添加别名。

对于 Linux 和 Windows,请重命名库标头中名称被别名的函数。 另一个可行的选项是,在引用新名称的文件中,#define old_name new_name,#include 导出被别名的库的标头,然后在调用者中#undef old_name。 如果有很多文件使用该库,一个更简单的替代方法是创建一个或多个标头来包装定义、包含和 undef,然后使用该标头。

希望这些信息有帮助!

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!

她如夕阳 2024-07-22 03:42:51

我从未使用过 dlsym、dlopen、dlerror、dlclose、dlvsym 等,但我正在查看手册页,它给出了打开 libm.so 并提取 cos 函数的示例。 dlopen 是否经历了寻找碰撞的过程? 如果没有,OP 可以手动加载这两个库,并为其库提供的所有函数分配新名称。

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.

软的没边 2024-07-22 03:42:51

如果是内置函数的话。
例如,torch 有 range 方法(已弃用),内置也有 range 方法。

我遇到了一些问题,只需在函数名称之前添加 __builtins__ 即可。
范围()=> 火炬
内置函数.range()

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()

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文