Link gegen eine Windows .dll+.lib-Dateikombination mit GCC unter Cygwin?

Lesezeit: 7 Minuten

Benutzeravatar von einpoklum
einpoklum

Ich weiß, wie man Bibliotheken in Unix-ähnlichen Kontexten verknüpft: Wenn ich mit arbeite .a oder .so Dateien gebe ich das Root-Suchverzeichnis mit an -L/my/path/to/lib/ und für libMylib füge ich hinzu -lMyLib.

Aber was, wenn ich habe

  • a .dll (zB im Windows\System32 Verzeichnis)?
  • a .dll (in Windows\System32) und ein .lib (irgendwo anders)?

Diese DLLs stammen von einer anderen Partei; Ich habe keinen Zugriff auf ihre Quellen – aber Zugriff auf die entsprechenden Include-Dateien, gegen die ich kompilieren kann.

  • Verwenden Sie den vollständigen Pfadnamen der .lib oder .dll Datei, Nr -L oder -lnur der Dateiname, wie in g++ -o foo.exe foo.o c:\something\somethingelse\some.lib. (Sie können auch die übliche -L/-l-Konvention verwenden, aber nur, wenn die Bibliotheksnamendatei mit ‘lib’ beginnt, was normalerweise unter Windows nicht der Fall ist).

    – nm

    31. Juli 2013 um 15:08 Uhr

  • @nm: Hat das, es hat nicht funktioniert … bist du sicher, dass das funktionieren soll?

    – einpoklum

    31. Juli 2013 um 15:39 Uhr

  • Funktioniert bei mir. Welche Fehler erhalten Sie?

    – nm

    31. Juli 2013 um 16:18 Uhr

  • Tut mir leid, das wiederzubeleben, aber ich habe das gleiche Problem, ich habe verschiedene Dinge ausprobiert, einschließlich Ihres Vorschlags @n.’pronomen’m. um direkt auf die lib-Datei zu verlinken. Aber ich erhalte immer noch einen Fehler “undefinierte Referenz”. Ich verwende make, das von qmake und g++ von mingw73_64 generiert wurde

    – mquasar

    18. Februar 2021 um 0:48 Uhr


  • Nur um hinzuzufügen, dass @n.18e9 insofern korrekt ist, als Sie den vollständigen Pfadnamen für die lib-Datei ohne die Optionen -L oder -l verwenden müssen. Dies verwendet x86_64-w64-mingw32/8.3.0 mit einer MSVC-generierten lib-Datei, nach viel Versuch und Irrtum. Ebenfalls, wichtig Stellen Sie sicher, dass Sie auf eine lib-Datei (und die zugehörige DLL) verlinken, die für a generiert wurde 64-Bit-Plattform (auf MSVC-Ziel X64, nicht Win32). Wenn Sie versuchen, eine 32-Bit-Lib-Datei zu verwenden, scheint g++ sie einfach zu ignorieren und Ihnen undefinierte Referenzen zu geben, während Sie sich die Haare raufen und alle Kombinationen ausprobieren.

    – David I

    15. Juli 2021 um 7:23 Uhr

Wenn Sie gegen a verlinken können .lib in Cygwin oder MinGW, dann können Sie (indirekt) gegen eine DLL verlinken.

In der MSVC-Welt ist es nicht ungewöhnlich, eine zu erstellen Bibliothek importieren zusammen mit einer DLL. Es ist eine statische Bibliothek (.lib), die die DLL lädt und die Schnittstelle der DLL umschließt. Sie rufen einfach die Wrapper-Funktionen in der (statischen) Importbibliothek auf und lassen die Importbibliothek alle DLL-bezogenen Dinge erledigen.

  • Für die Windows-API gibt es Importbibliotheken im WindowsSDK.
  • Für Ihre eigenen MSVC-DLLs kann MSVC die Importbibliotheken automatisch generieren, wenn Sie die DLL erstellen.
  • Für eine DLL eines Drittanbieters können Sie basierend auf den entsprechenden Header-Dateien eine statische Wrapper-Bibliothek erstellen.

Verknüpfung gegen die .lib Datei in Cygwin oder MinGW ist möglich. Beispiel:

g++ -o myprg myprg.o -lShlwapi

Dies verlinkt gegen Shlwapi.lib. (Die Bibliothek muss sich im lokalen Verzeichnis oder im Bibliothekspfad des Linkers befinden.)

Das Linken gegen Importbibliotheken von DLLs funktioniert auf die gleiche Weise.

Hinweis 1: Beachten Sie die unterschiedlichen ABIs und Namensmangel. Das Aufrufen von einfachen C-Funktionen in DLL- oder LIB-Dateien funktioniert jedoch in den meisten Fällen.

Hinweis 2: Denken Sie daran, dass g++ erfordert, dass die Bibliotheken in der richtigen Reihenfolge angegeben werden.

  • Das funktioniert bei mir nicht; Ich beschäftige mich schon seit Tagen damit und bekomme keine Lösung. Immer wenn ich die Bibliothek verlinke, erhalte ich die Fehlermeldung “undefinierter Verweis auf …”.

    – Duck Dodgers

    6. März um 17:43 Uhr

  • @DuckDodgers, kannst du 1-3 undefinierte Symbole nennen? Mit welcher Bibliothek verlinken Sie?

    – ManuelAtWork

    7. März um 7:48

  • Danke für die Antwort. Ich verlinke auf eine benutzerdefinierte Bibliothek namens: HTUSB. Ich habe statische und dynamische Bibliotheken, die ich mit meinem C++-Programm verknüpfen möchte. Hier ist ein Bild meiner Ordnerstruktur: ibb.co/jf0xXHd. Ich habe die DLL- und .lib-Datei an zwei Stellen abgelegt, nur für den Fall, dass die Ordnerstruktur das Problem war. Schließlich ist hier der Befehl, den ich verwende, um die Dateien zu verknüpfen: g++ decibel_test.cpp -I\Users\13122\OneDrive\Desktop\decibel -L”\Users\13122\OneDrive\Desktop\decibel\HTUSB.dll”. Und hier ist ein Fehler “undefinierter Verweis auf `_imp__HTUSB_Close@0′” HTUSB_CLOSE ist eine der Funktionen in der Bibliothek

    – Duck Dodgers

    8. März um 21:43 Uhr


  • Bitte überprüfen Sie, ob die Importbibliothek (.lib) das angegebene Symbol exportiert. (dumpbin Befehl, bzw nm unter Cygwin). Stellen Sie außerdem sicher, dass Namensmangel (und Aufrufkonventionen) übereinstimmen, was ein Problem sein kann, wenn die Bibliothek mit einem anderen Compiler (= anderen ABIs) kompiliert wurde.

    – ManuelAtWork

    9. März um 8:25

  • Erstmal vielen Dank für die kontinuierliche Antwort! Zweitens führe ich “nm F HTUSB.lib” aus und erhalte “keine solche Datei oder kein solches Verzeichnis”. Aber dann führe ich “nm F HTUSB.dll) aus und erhalte “keine Symbole”. Seltsam, weil die DLL-Datei definitiv nicht leer ist und die .lib-Datei definitiv existiert. Entschuldigung, wenn die Fragen albern erscheinen; ich bin neu darin

    – Duck Dodgers

    9. März um 20:25 Uhr

Benutzeravatar von David I
David I

@einpoklum Konvertieren meines Kommentars in eine Antwort: @n.18e9 ist insofern richtig, als Sie den vollständigen Pfadnamen für die lib-Datei ohne die Optionen -L oder -l verwenden müssen.
g++ -o foo.exe foo.o c:\something\somethingelse\some.lib. Sie können auch direkt auf die Windows-DLL-Datei verlinken g++ -o foo.exe foo.o c:\something\somethingelse\some.dll.

Wichtig – Stellen Sie sicher, dass Sie auf eine lib-Datei (und zugehörige DLL) verlinken, die für a 64-Bit-Plattform (auf MSVC-Ziel X64, nicht Win32).

OK, du wolltest ein Beispiel, lass uns gehen.

Hier sind zwei Beispiele, die gcc/g++ verwenden, um eine Verknüpfung zu einer Windows-nativen DLL herzustellen, die einfache C-Funktionen exportiert (unter Verwendung von x86_64-w64-mingw32/8.3.0 unter Windows 10).

Ich verwende meine eigene kostenlose xmlsq-Bibliothek als Beispiel https://www.cryptosys.net/xmlsq. Sie können die native Kern-DLL und den gesamten unten zitierten Quellcode herunterladen. Stellen Sie sicher, dass Sie die 64-Bit-DLL verwenden.

Die native Windows-DLL diXmlsq.dll ist vollständig in reinem C-Code geschrieben und exportiert einfache C-Funktionen (extern “C”). Insbesondere exportiert es für dieses Beispiel a XMLSQ_Gen_Version Funktion, die einen ganzzahligen Wert zurückgibt. Die DLL wurde mit MSVC 12.0 für die X64-Plattform kompiliert. Die zugehörige Bibliotheksdatei, die von MSVC generiert wird, ist diXmlsq.lib.

Ich sollte hinzufügen, dass diese DLL genauso funktioniert wie eine Windows “Win32 API” DLL, also sollten die Anweisungen hier für die Standard-Windows-Bibliotheken in funktionieren Windows\System32 (Stellen Sie erneut sicher, dass Sie gegen die 64-Bit-Version verlinken).

Beispiel 1. Eine einfache C-Schnittstelle.

Diese beiden Befehle werden auf meinem System ohne Warnung kompiliert:

> gcc -o test-ver test-ver.c "C:\fullpath\to\x64\diXmlsq.lib"

> gcc -o test-ver test-ver.c "C:\fullpath\to\x64\diXmlsq.dll"

diXmlsq.dll wird mit der folgenden Definitionsdatei kompiliert. (Sie könnten alternativ verwenden __declspec(dllexport))

Ref: https://learn.microsoft.com/en-us/cpp/build/exporting-from-a-dll?view=msvc-160

diXmlsq.def

LIBRARY      "diXmlsq"
EXPORTS
    XMLSQ_Gen_Version

diXmlsq.h – die C-Schnittstelle zu diXmlsq.dll

#ifdef __cplusplus
extern "C" {
#endif

long __stdcall XMLSQ_Gen_Version(void);

#ifdef __cplusplus
}
#endif

So rufen Sie die Kernfunktion in einem einfachen C-Programm auf:

test-ver.c

#include <stdio.h>
#include "diXmlsq.h"
int main(void)
{
    long n;
    n = XMLSQ_Gen_Version();
    printf("Version = %ld\n", n);
    return 0;
}

Beispiel 2. Eine C++-Schnittstelle.

Beide Befehle werden ohne Warnung mit g++ kompiliert.

> g++ -o test-simple test-simple.cpp xmlsq.cpp "C:\fullpath\to\x64\diXmlsq.lib"

> g++ -o test-simple test-simple.cpp xmlsq.cpp "C:\fullpath\to\x64\diXmlsq.dll"

Die Idee der C++-Schnittstelle ist es, eine Schnittstelle zur einfachen C-Bibliothek zu sein, die die bequemeren STL-Typen wie verwendet std::string und std::vector. Um die Dinge einfach zu halten, demonstrieren wir nur die Gen::Version Methode.

Auszüge des C++-Codes folgen:

test-simple.cpp – ein Test-C++-Programm.

#include <iostream>
#include "xmlsq.hpp"
int main()
{
    std::cout << "xmlsq::Gen::Version=" << xmlsq::Gen::Version() << std::endl;
}

xmlsq.hpp – die C++-Schnittstelle

namespace xmlsq
{
    class Gen {
    private:
        Gen() {} // Static methods only, so hide constructor.
    public:
        /** Get version number of core diXmlsq DLL. */
        static int Version();
    };
}

xmlsq.cpp – die C++-Implementierung.

#include "diXmlsq.h"
#include "xmlsq.hpp"

namespace xmlsq
{
    int Gen::Version() {
        int n = XMLSQ_Gen_Version();
        return n;
    }
}

Beispiel 3. Es wurde versehentlich versucht, eine Verbindung zur 32-Bit-Bibliothek herzustellen.

> gcc -o test-ver test-ver.c "C:\fullpath\to\Win32\diXmlsq.lib"
C:/Strawberry/c/bin/../lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: 
C:\Users\user\AppData\Local\Temp\cce27Dhl.o:test-ver.c:(.text+0xe): 
undefined reference to `XMLSQ_Gen_Version'
collect2.exe: error: ld returned 1 exit status

  • Sie erhalten +1 für die Mühe, noch bevor ich Zeit hatte, mich darum zu kümmern 🙂

    – einpoklum

    19. Juli 2021 um 16:25 Uhr

1432350cookie-checkLink gegen eine Windows .dll+.lib-Dateikombination mit GCC unter Cygwin?

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

Privacy policy