Was soll ich tun, wenn zwei Bibliotheken eine Funktion mit demselben Namen bereitstellen, die einen Konflikt verursacht?

Lesezeit: 7 Minuten

Benutzeravatar von qeek
quiek

Was soll ich tun, wenn ich zwei Bibliotheken habe, die Funktionen mit äquivalenten Namen bereitstellen?

  • Sind diese statischen Bibliotheken oder dynamisch verknüpft?

    – Alnitak

    24. März 2009 um 16:54 Uhr

  • wir brauchen mehr Details… werden diese Namen exportiert? oder werden sie nur intern verwendet? Kannst du die Namen ändern?

    – Johannes Schaub – litb

    24. März 2009 um 17:02 Uhr

  • Sie sind beide dynamisch verknüpft. Ich kann die Namen nicht ändern, da ich die Bibliotheken nicht besitze.

    – quiek

    24. März 2009 um 17:18 Uhr

  • Tolle Frage. Natürlich wäre es bei diesen beiden Bibliotheken kein Problem, wenn allen Symbolen eine eindeutige ID vorangestellt wäre (z vorbis_..., sf_..., sdl_...). Dies ist im Wesentlichen das, was C++ mit den Symbolnamen für Namespace-Funktionen macht.

    – Vorticus

    22. Dezember 2013 um 6:20 Uhr

  • Dies ist eine sehr interessante Frage, aber leider zu ungenau, weshalb zu viele zu breite Antworten gegeben werden.

    – jugr

    6. Mai 2019 um 10:39 Uhr

Bens Benutzeravatar
Ben

Es ist möglich, Symbole in einer Objektdatei mit umzubenennen objcopy --redefine-sym old=new file (siehe man objcopy).

Rufen Sie dann einfach die Funktionen mit ihren neuen Namen auf und verknüpfen Sie sie mit der neuen Objektdatei.

  • Nett. Dies wäre trivial zu einem Makefile hinzuzufügen. Wenn die Bibliotheken jemals aktualisiert werden, wäre eine Objcopy-Beschwörung viel einfacher zu aktualisieren als einige der anderen Lösungen.

    – Sigissaft

    25. März 2009 um 6:24 Uhr

  • Vergessen Sie nicht, auch die Symbole in den Header-Dateien umzubenennen.

    – mouviciel

    2. April 2009 um 11:56 Uhr

  • ^ sed/awk/perl wäre auch nützlich, um die Umbenennung der Symbole im Header zu automatisieren

    – Alex Reinking

    6. März 2019 um 20:06 Uhr

dmckee --- Benutzeravatar des Ex-Moderators Kitten
dmckee — Ex-Moderator-Kätzchen

  • Wenn Sie einen oder beide steuern: Bearbeiten Sie einen, um den Namen zu ändern und neu zu kompilieren. Oder sehen Sie sich gleichermaßen die Antworten von Ben und unknown an, die funktionieren ohne Zugriff auf den Quellcode.
  • Wenn Sie keinen von beiden kontrollieren, können Sie einen von ihnen einpacken. Das ist kompilieren Ein weiterer (statisch verknüpft!)-Bibliothek, die nichts tut, außer alle Symbole des Originals erneut zu exportieren, mit Ausnahme des störenden Symbols, das über einen Wrapper mit einem alternativen Namen erreicht wird. Was für ein Aufwand.
  • Später hinzugefügt: Da qeek sagt, dass er über dynamische Bibliotheken spricht, sind die von Ferruccio und mouviciel vorgeschlagenen Lösungen wahrscheinlich die besten. (Ich scheine in längst vergangenen Tagen zu leben, als die statische Verknüpfung die Standardeinstellung war. Es färbt mein Denken.)

Apropos zu den Kommentaren: Mit “exportieren” meine ich Module sichtbar zu machen, die auf die Bibliothek verlinken—entspricht der extern Schlüsselwort im Dateibereich. Wie dies gesteuert wird, hängt vom Betriebssystem und Linker ab. Und es ist etwas, was ich stets muss nachschauen.

  • Das war auch mein erster Gedanke, aber wirst du nicht mit dem gleichen Kollisionsproblem enden? Am Ende muss das gesamte Projekt gelinkt werden – zum Zeitpunkt des Kompilierens/Linkens oder zur Laufzeit – zu welchem ​​Zeitpunkt beide störenden Bibliotheken so geladen werden müssen, wie sie sind.

    – Sniggerfardimungus

    24. März 2009 um 17:10 Uhr

  • @unknown: Die Verpackung muss mit statischer Verknüpfung kompiliert werden und sollte das anstößige Symbol nicht exportieren. Dann können Sie den Wrapper immer noch dynamisch verknüpfen. Für mehr Klarheit bearbeitet, danke.

    – dmckee — Ex-Moderator-Kätzchen

    24. März 2009 um 17:13 Uhr

  • Wenn das Problem von qeek bei ddls und nicht bei statischen Bibliotheken liegt, wie ist es dann möglich, eine neue Bibliothek mit einem Wrapper zu erstellen? Da die Wrapper-Bibliothek dynamisch eine Funktion in der Bibliothek umschließen müsste, mit der Sie überhaupt nicht verknüpfen möchten.

    – JeffD

    24. März 2009 um 17:14 Uhr

  • @dmckee – was meinst du mit “exportieren”?

    anon

    24. März 2009 um 17:22 Uhr

  • Vielleicht könnte jemand ein einfaches Beispiel für diese Technik geben? Eine exe, zwei Bibliotheken, die jeweils eine Funktion mit demselben Namen enthalten.

    anon

    24. März 2009 um 18:13 Uhr

Unter Windows könnten Sie verwenden LoadLibrary() um eine dieser Bibliotheken in den Speicher zu laden und dann zu verwenden GetProcAddress() Um die Adresse jeder Funktion zu erhalten, müssen Sie die Funktionen über einen Funktionszeiger aufrufen und aufrufen.

z.B

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

würde die Adresse einer Funktion namens bar in foo.dll bekommen und sie aufrufen.

Ich weiß, dass Unix-Systeme ähnliche Funktionen unterstützen, aber mir fallen ihre Namen nicht ein.

  • dlopen dlsymund dlclose. Die Kapselung unter Unix ist jedoch möglicherweise nicht so effektiv wie unter Windows.

    – Benutzer877329

    3. Oktober 2016 um 7:11 Uhr

  • Eine automatisierte Lösung für Linux

    – jugr

    6. Mai 2019 um 10:29 Uhr

Benutzeravatar von uol3c
uol3c

Wenn Sie dort .o-Dateien haben, finden Sie hier eine gute Antwort: https://stackoverflow.com/a/6940389/4705766

Zusammenfassung:

  1. objcopy --prefix-symbols=pre_string test.o um die Symbole in der .o-Datei umzubenennen

oder

  1. objcopy --redefine-sym old_str=new_str test.o um das spezifische Symbol in der .o-Datei umzubenennen.

Benutzeravatar von Sniggerfardimungus
Sniggerfardimungus

Hier ist ein Gedanke. Öffnen Sie eine der störenden Bibliotheken in einem Hex-Editor und ändern Sie alle Vorkommen der störenden Zeichenfolgen in etwas anderes. Sie sollten die neuen Namen dann bei allen zukünftigen Anrufen verwenden können.

AKTUALISIEREN: Ich habe es gerade an diesem Ende gemacht und es scheint zu funktionieren. Natürlich habe ich das nicht gründlich getestet – es ist vielleicht nicht mehr als eine wirklich gute Möglichkeit, sich mit einer Hexedit-Schrotflinte das Bein wegzublasen.

  • eigentlich keine schreckliche Lösung. Ein bisschen hackish, aber alles, was Sie tun würden, ist, die Zeichenfolgen in der Symboltabelle zu ändern. Darin besteht kein wirklicher funktioneller Schaden.

    – Evan Teran

    24. März 2009 um 17:52 Uhr

  • Sie möchten wahrscheinlich auch die Bibliothek umbenennen – damit nicht jemand anderes vorbeikommt und versucht, das Ding erneut zu laden. Sie würden von einem Konflikt zu Dutzenden oder Hunderten übergehen. =]Ich liebe das an Stackoverflow: Wir haben eine getestete Antwort auf eine Frage und sie hat 3 Stimmen. Die erste (unvollständige) Antwort: 17. =]

    – Sniggerfardimungus

    26. März 2009 um 20:04 Uhr

  • Die Umbenennungsmöglichkeiten sind begrenzt, da Sie nur Namen erstellen können kürzer. Auch unter Linux werden Sie Schwierigkeiten haben, ELF-Hash-Tabellen zu aktualisieren.

    – jugr

    6. Mai 2019 um 10:35 Uhr

Benutzeravatar von mouviciel
mouviciel

Sie sollten sie nicht zusammen verwenden. Wenn ich mich richtig erinnere, gibt der Linker in einem solchen Fall einen Fehler aus.

Ich habe es nicht versucht, aber eine Lösung kann mit sein dlopen(), dlsym() und dlclose() die es Ihnen ermöglichen, dynamische Bibliotheken programmgesteuert zu handhaben. Wenn Sie die beiden Funktionen nicht gleichzeitig benötigen, können Sie die erste Bibliothek öffnen, die erste Funktion verwenden und die erste Bibliothek schließen, bevor Sie die zweite Bibliothek/Funktion verwenden.

  • eigentlich keine schreckliche Lösung. Ein bisschen hackish, aber alles, was Sie tun würden, ist, die Zeichenfolgen in der Symboltabelle zu ändern. Darin besteht kein wirklicher funktioneller Schaden.

    – Evan Teran

    24. März 2009 um 17:52 Uhr

  • Sie möchten wahrscheinlich auch die Bibliothek umbenennen – damit nicht jemand anderes vorbeikommt und versucht, das Ding erneut zu laden. Sie würden von einem Konflikt zu Dutzenden oder Hunderten übergehen. =]Ich liebe das an Stackoverflow: Wir haben eine getestete Antwort auf eine Frage und sie hat 3 Stimmen. Die erste (unvollständige) Antwort: 17. =]

    – Sniggerfardimungus

    26. März 2009 um 20:04 Uhr

  • Die Umbenennungsmöglichkeiten sind begrenzt, da Sie nur Namen erstellen können kürzer. Auch unter Linux werden Sie Schwierigkeiten haben, ELF-Hash-Tabellen zu aktualisieren.

    – jugr

    6. Mai 2019 um 10:35 Uhr

Benutzeravatar der Community
Gemeinschaft

Angenommen, Sie verwenden Linux, müssen Sie zuerst hinzufügen

#include <dlfcn.h>

Deklarieren Sie die Funktionszeigervariable im richtigen Kontext, z. B.

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

Wie Ferruccio in https://stackoverflow.com/a/678453/1635364 angegeben hat, laden Sie explizit die Bibliothek, die Sie verwenden möchten, indem Sie sie ausführen (wählen Sie Ihre bevorzugten Flags).

void* dlhandle;
void* sym;

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

Lesen Sie die Adresse der Funktion, die Sie später aufrufen möchten

sym = dlsym(dlhandle, "conflicting_server_init");

wie folgt zuweisen und werfen

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

Rufen Sie auf ähnliche Weise wie das Original auf. Entladen Sie schließlich durch Ausführen

dlclose(dlhandle);

1422770cookie-checkWas soll ich tun, wenn zwei Bibliotheken eine Funktion mit demselben Namen bereitstellen, die einen Konflikt verursacht?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy