簡體   English   中英

如果兩個庫提供同名的 function 產生沖突怎么辦?

[英]What should I do if two libraries provide a function with the same name generating a conflict?

如果我有兩個提供同名函數的庫,我該怎么辦?

可以使用objcopy --redefine-sym old=new file重命名 object 文件中的符號(參見 man objcopy)。

然后只需使用它們的新名稱調用這些函數並鏈接到新的 object 文件。

  • 如果您控制一個或兩個:編輯一個以更改名稱並重新編譯或等效地查看Benunknown的答案,這將在無需訪問源代碼的情況下工作。
  • 如果您不控制其中任何一個,則可以將其中一個包裹起來。 那就是編譯另一個靜態鏈接的)庫,除了重新導出原始符號之外的所有符號之外什么都不做。 這是通過具有備用名稱的包裝器到達的。 真麻煩。
  • 稍后添加:由於 qeek 說他在談論動態庫,因此Ferrucciomouviciel建議的解決方案可能是最好的。 (我似乎生活在很久以前 static 鏈接是默認的。我的想法是 colors。)

適當的評論:“導出”是指使鏈接到庫的模塊可見——相當於文件 scope 中的extern關鍵字。 這是如何控制的取決於操作系統和 linker。 這是我必須經常查找的東西。

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.

例如

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 的 function 的地址並調用它。

我知道 Unix 系統支持類似的功能,但我想不出它們的名字。

如果你有 .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重命名特定符號 in.o 文件。

這是一個想法。 在十六進制編輯器中打開一個有問題的庫,並將所有出現的有問題的字符串更改為其他內容。 然后,您應該能夠在以后的所有呼叫中使用新名稱。

更新:我只是為此做了它,它似乎工作。 當然,我還沒有徹底測試過這個——它可能只是用六角霰彈槍把你的腿炸掉的好方法。

假設您使用 linux 您首先需要添加

#include <dlfcn.h>

在適當的上下文中聲明 function 指針變量,例如,

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

就像https://stackoverflow.com/a/678453/1635364中所述的 Ferruccio 一樣,通過執行顯式加載要使用的庫(選擇您喜歡的標志)

void* dlhandle;
void* sym;

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

讀取后面要調用的function的地址

sym = dlsym(dlhandle, "conflicting_server_init");

分配和轉換如下

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

調用方式與原始方式類似。 最后,通過執行卸載

dlclose(dlhandle);

你不應該一起使用它們。 如果我沒記錯的話,linker 在這種情況下會發出錯誤。

我沒有嘗試,但解決方案可能是dlopen()dlsym()dlclose() ,它們允許您以編程方式處理動態庫。 如果您不需要同時使用這兩個函數,您可以打開第一個庫,使用第一個 function 並在使用第二個庫/函數之前關閉第一個庫。

發誓? 據我所知,如果您有兩個庫公開了具有相同名稱的鏈接點並且您需要鏈接這兩個庫,那么您無能為力。

這個問題是 c++ 有命名空間的原因。 對於兩個具有相同名稱的第三方庫,c 並沒有真正好的解決方案。

如果它是動態 object,您可能能夠顯式加載共享對象(LoadLibrary/dlopen/etc)並以這種方式調用它。 或者,如果您不需要在同一代碼中同時使用兩個庫,您可以使用 static 鏈接(如果您有 .lib/.a 文件)來做一些事情。

當然,這些解決方案都不適用於所有項目。

這個問題已經接近十年了,但一直有新的搜索......

正如已經回答的那樣,帶有 --redefine-sym 標志的 objcopy 在 Linux 中是一個不錯的選擇。 例如,請參閱https://linux.die.net/man/1/objcopy以獲取完整文檔。 這有點笨拙,因為您實際上是在進行更改時復制整個庫,並且每次更新都需要重復這項工作。 但至少它應該工作。

對於 Windows,動態加載庫是一種解決方案,也是一種永久性解決方案,就像 Linux 中的 dlopen 替代方案一樣。 但是 dlopen() 和 LoadLibrary() 都添加了額外的代碼,如果唯一的問題是重復名稱,則可以避免這些代碼。 這里的 Windows 解決方案比 objcopy 方法更優雅:只需告訴 linker 庫中的符號以其他名稱已知並使用該名稱。 有幾個步驟可以做到這一點。 您需要制作一個 def 文件並在 EXPORTS 部分提供名稱翻譯。 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更永久)以獲得 def 文件的完整語法詳細信息。 該過程是為其中一個庫創建一個 def 文件,然后使用該 def 文件構建一個 lib 文件,然后與該 lib 文件鏈接。 (對於 Windows DLL,lib 文件僅用於鏈接,而不是代碼執行。)請參閱How to make a.lib file when has a.dll 文件和 Z099FB995346F31C749F6E40DB0F395EZ 文件的構建過程這里唯一的區別是添加別名。

對於 Linux 和 Windows,重命名庫標題中的函數,其名稱被別名。 另一個應該起作用的選項是,在引用新名稱的文件中,#define old_name new_name,#include 導出被別名的庫的標題,然后在調用者中使用 #undef old_name。 如果有很多文件使用該庫,則更簡單的替代方法是制作 header 或包裝定義、包含和取消定義的標頭,然后使用該 header。

希望這些信息對您有所幫助!

您應該圍繞其中一個編寫包裝庫。 您的包裝庫應該公開具有唯一名稱的符號,而不是公開非唯一名稱的符號。

您的另一個選擇是重命名 header 文件中的 function 名稱,並重命名庫 object 存檔中的符號。

無論哪種方式,要同時使用兩者,這將是一項黑客工作。

我從未使用過 dlsym、dlopen、dlerror、dlclose、dlvsym 等,但我正在查看手冊頁,它提供了一個打開 libm.so 並提取 cos function 的示例。 dlopen go 是否通過尋找碰撞的過程? 如果沒有,OP 可以手動加載這兩個庫,並為他的庫提供的所有功能分配新名稱。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM