Frage

Ich schreibe eine C/C++-DLL und möchte bestimmte Funktionen exportieren, die ich zuvor mit einer solchen .def-Datei durchgeführt habe

LIBRARY "MyLib"
EXPORTS
  Foo
  Bar

mit dem so definierten Code, zum Beispiel:

int Foo(int a);
void Bar(int foo);

Was aber, wenn ich eine überladene Methode von Foo() deklarieren möchte, wie zum Beispiel:

int Foo(int a, int b);

Da die Def-Datei nur den Funktionsnamen und nicht den vollständigen Prototyp enthält, kann ich mir nicht vorstellen, wie sie mit den überladenen Funktionen umgehen würde.Verwenden Sie einfach den einen Eintrag und geben Sie dann an, welche überladene Version Sie möchten, wenn Sie den ordnungsgemäß prototypischen Funktionszeiger an LoadLibrary() übergeben?

Bearbeiten:Um es klarzustellen: Dies geschieht unter Windows mit Visual Studio 2005

Bearbeiten:Habe die Nicht-Def-Methode (__declspec) als Antwort markiert ... Ich weiß, dass dies das Problem mit der Verwendung von Def-Dateien nicht wie gewünscht löst, aber es scheint, dass es wahrscheinlich keine (offizielle) Lösung mit Def-Dateien gibt.Ich lasse die Frage jedoch offen, falls jemand etwas weiß, wir haben keine überladenen Funktionen und Def-Dateien.

War es hilfreich?

Lösung

Markieren Sie im Code selbst die Funktionen, die Sie exportieren möchten, mit __declspec(dllexport).Zum Beispiel:

#define DllExport __declspec(dllexport)

int DllExport  Foo( int a ) {
  // implementation
}
int DllExport Foo( int a, int b ) {
  // implementation
}

Wenn Sie dies tun, müssen Sie die Funktionen nicht in der .def-Datei auflisten.

Alternativ können Sie möglicherweise einen Standardparameterwert verwenden, wie zum Beispiel:

int Foo( int a, int b = -1 )

Dies setzt voraus, dass es einen Wert für b gibt, mit dem Sie angeben können, dass er nicht verwendet wird.Wenn -1 ein zulässiger Wert für b ist oder es keinen Standardwert gibt oder geben sollte, funktioniert dies nicht.

Bearbeiten (Adam Haile):Die Verwendung von __declspec wurde korrigiert, da __dllspec nicht korrekt war, sodass ich dies als offizielle Antwort markieren konnte ... es war nahe genug.

Bearbeiten (Graeme):Ups – danke für die Korrektur meines Tippfehlers!

Andere Tipps

Funktionsüberladung ist eine C++-Funktion, die auf Namensmangling (den kryptischen Funktionsnamen in den Linker-Fehlermeldungen) beruht.

Indem ich die entstellten Namen in die Def-Datei schreibe, kann ich mein Testprojekt verknüpfen und ausführen:

LIBRARY "TestDLL"
EXPORTS
    ?Foo@@YAXH@Z
    ?Foo@@YAXHH@Z

scheint zu funktionieren

void Foo( int x );
void Foo( int x, int y );

Kopieren Sie also die C++-Funktionsnamen aus der Fehlermeldung und schreiben Sie sie in Ihre Def-Datei.Die eigentliche Frage ist jedoch:Warum möchten Sie eine Def-Datei verwenden und nicht __declspec(dllexport) verwenden?

Die verstümmelten Namen sind nicht portierbar, ich habe sie mit VC++ 2008 getestet.

Ich hatte ein ähnliches Problem, deshalb wollte ich auch dazu posten.

  1. Normalerweise verwendet

    extern "C" __declspec(dllexport) void Foo();
    

    Einen Funktionsnamen zu exportieren ist in Ordnung.Es wird normalerweise Exportieren Sie den Namen nicht, ohne dass eine .DEF -Datei erforderlich ist.Es gibt jedoch einige Ausnahmen wie __stdcall -Funktionen und überlastete Funktionsnamen.

  2. Wenn Sie eine Funktion deklarieren, um die __stdcall -Konvention zu verwenden (wie für viele API -Funktionen) dann

    extern "C" __declspec(dllexport) void __stdcall Foo();
    

    Wird einen verstümmelten Namen wie _foo@4 exportieren.In diesem Fall müssen Sie möglicherweise den exportierten Namen explizit einem internen verstümmelten Namen abbilden.

A.So exportieren Sie einen entschlüsselten Namen.In einer .def-Datei hinzufügen

----
EXPORTS
    ; Explicit exports can go here

    Foo
-----

Dadurch wird versucht, eine „beste Übereinstimmung“ für eine interne Funktion Foo zu finden und diese zu exportieren.Im obigen Fall, wo es nur one foo dies erzeugt das Mapping

Foo = _Foo@4

wie über dumpbin /EXPORTS ersichtlich ist

Wenn Sie einen Funktionsnamen überladen haben, müssen Sie möglicherweise explizit angeben, welche Funktion Sie in der .def-Datei wünschen. indem Sie einen verzerrten Namen mit der Syntax entryname[=internalname] angeben.z.B.

----
EXPORTS
    ; Explicit exports can go here

    Foo=_Foo@4
-----

B.Eine Alternative zu .def-Dateien besteht darin, dass Sie Namen „an Ort und Stelle“ mithilfe eines #pragma exportieren können.

#pragma comment(linker, "/export:Foo=_Foo@4")

C.Eine dritte Alternative besteht darin, nur eine Version von Foo als externes „C“ zu deklarieren, um sie unverfälscht zu exportieren.Sehen Hier für Details.

Es gibt keine offizielle Möglichkeit, das zu tun, was Sie wollen, da die DLL-Schnittstelle eine C-API ist.

Als Workaround verwendet der Compiler selbst verstümmelte Namen. Daher sollten Sie die Namensverstümmelung verwenden, wenn Sie nicht zu viel an Ihrem Code ändern möchten.

Es gibt keine sprach- oder versionunabhängige Möglichkeit, eine überladene Funktion zu exportieren, da sich die Mangling-Konvention mit jeder Version des Compilers ändern kann.

Dies ist einer der Gründe, warum die meisten WinXX-Funktionen lustige Namen wie *Ex oder *2 haben.

Systax für EXPORTS-Definition ist:

entryname[=internalname] [@ordinal [NONAME]] [PRIVATE] [DATA]

Eintragsname ist der Funktions- oder Variablenname, den Sie exportieren möchten.Dies ist erforderlich.Wenn sich der Name, den Sie exportieren, vom Namen in der DLL unterscheidet, geben Sie den Namen des Exports in der DLL mit internalname an.

Wenn Ihre DLL beispielsweise die Funktion func1() exportiert und Sie möchten, dass sie als func2() verwendet wird, geben Sie Folgendes an:

EXPORTS
func2=func1

Sehen Sie sich einfach die verstümmelten Namen an (mit dem Dependency Walker) und geben Sie Ihren eigenen Funktionsnamen an.

Quelle: http://msdn.microsoft.com/en-us/library/hyx1zcd3(v=vs.71).aspx

Bearbeiten:Dies funktioniert für dynamische DLLs, bei denen wir GetProcAddress() verwenden müssen, um Funktionen in der DLL explizit abzurufen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top