Domanda

Sto scrivendo una DLL C/C++ e desidero esportare alcune funzioni che ho eseguito prima di utilizzare un file .def come questo

LIBRARY "MyLib"
EXPORTS
  Foo
  Bar

con il codice definito così, ad esempio:

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

Tuttavia, cosa succede se voglio dichiarare un metodo sovraccaricato di Foo() come:

int Foo(int a, int b);

Poiché il file def ha solo il nome della funzione e non il prototipo completo, non riesco a vedere come gestirebbe le funzioni sovraccaricate.Utilizzi semplicemente l'unica voce e quindi specifichi quale versione sovraccaricata desideri quando passi il puntatore a funzione adeguatamente prototipato a LoadLibrary() ?

Modificare:Per essere chiari, questo è su Windows che utilizza Visual Studio 2005

Modificare:Contrassegnato il metodo non def (__declspec) come risposta... So che questo in realtà non risolve il problema utilizzando i file def come volevo, ma sembra che probabilmente non esista alcuna soluzione (ufficiale) utilizzando i file def.Lasceremo la questione aperta, tuttavia, nel caso qualcuno sappia qualcosa non abbiamo funzioni sovraccaricate e file def.

È stato utile?

Soluzione

Nel codice stesso, contrassegna le funzioni che desideri esportare utilizzando __declspec(dllexport).Per esempio:

#define DllExport __declspec(dllexport)

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

In questo caso non è necessario elencare le funzioni nel file .def.

In alternativa, potresti essere in grado di utilizzare un valore di parametro predefinito, come:

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

Ciò presuppone che esista un valore per b che puoi utilizzare per indicare che non è utilizzato.Se -1 è un valore legale per b, o se non c'è o non dovrebbe esserci un valore predefinito, questo non funzionerà.

Modifica (Adam Haile):Corretto per utilizzare __declspec poiché __dllspec non era corretto, quindi ho potuto contrassegnarlo come risposta ufficiale... era abbastanza vicino.

Modifica (Graeme):Ops, grazie per aver corretto il mio errore di battitura!

Altri suggerimenti

L'overload delle funzioni è una funzionalità C++ che si basa sulla manipolazione dei nomi (i nomi criptici delle funzioni nei messaggi di errore del linker).

Scrivendo i nomi alterati nel file def, posso collegare ed eseguire il mio progetto di test:

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

sembra funzionare per

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

Quindi copia i nomi delle funzioni C++ dal messaggio di errore e scrivili nel tuo file def.Tuttavia la vera domanda è:Perché vuoi utilizzare un file def e non utilizzare __declspec(dllexport) ?

I nomi alterati non sono portabili, ho testato con VC++ 2008.

Ho avuto un problema simile quindi volevo pubblicare anche questo.

  1. Di solito si usa

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

    esportare il nome di una funzione va bene.Lo farà Generalmente Esporta il nome Unmangled senza la necessità di un file .def.Vi sono, tuttavia, alcune eccezioni come __stdcall funzioni e nomi di funzioni sovraccarichi.

  2. Se si dichiara una funzione per utilizzare la convenzione __stdCall (come è fatto per molte funzioni API), allora

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

    Esporterà un nome mangellato come _foo@4.In questo caso potrebbe essere necessario mappare esplicitamente il nome esportato in un nome interno interno.

UN.Come esportare un nome non alterato.In un file .def aggiungi

----
EXPORTS
    ; Explicit exports can go here

    Foo
-----

Questo proverà a trovare una "corrispondenza migliore" per una funzione interna Foo e ad esportarla.Nel caso sopra in cui esiste un solo foo questo creerà la mappatura

Pippo = _Pippo@4

come si può vedere tramite dumpbin /EXPORTS

Se hai sovraccaricato un nome di funzione, potrebbe essere necessario dire esplicitamente quale funzione desideri nel file .Def specificando un nome Mangled usando la sintassi EntryName [= InternalName].per esempio.

----
EXPORTS
    ; Explicit exports can go here

    Foo=_Foo@4
-----

B.Un'alternativa ai file .def è che puoi esportare i nomi "sul posto" utilizzando un #pragma.

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

C.Una terza alternativa è dichiarare solo una versione di Foo come extern "C" da esportare senza modifiche.Vedere Qui per dettagli.

Non esiste un modo ufficiale per fare quello che vuoi, perché l'interfaccia dll è un C api.

Il compilatore stesso utilizza nomi alterati come soluzione alternativa, quindi dovresti utilizzare la alterazione dei nomi quando non vuoi cambiare troppo nel tuo codice.

Non esiste un modo indipendente dalla lingua o dalla versione per esportare una funzione sovraccaricata poiché la convenzione di modifica può cambiare con ogni versione del compilatore.

Questo è uno dei motivi per cui la maggior parte delle funzioni WinXX hanno nomi divertenti come *Ex o *2.

La definizione di Systax per EXPORTS è:

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

nomeentrata è il nome della funzione o della variabile che desideri esportare.Questo è necessario.Se il nome che esporti è diverso dal nome nella DLL, specifica il nome dell'esportazione nella DLL con internalname.

Ad esempio, se la tua DLL esporta una funzione, func1() e desideri che venga utilizzata come func2(), dovrai specificare:

EXPORTS
func2=func1

Basta vedere i nomi alterati (usando Dependency Walker) e specificare il nome della propria funzione.

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

Modificare:Funziona con DLL dinamiche, dove dobbiamo utilizzare GetProcAddress() per recuperare esplicitamente una funzione in Dll.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top