File .def DLL C / C ++

Non sto capendo il motivo dell’utilizzo di file .def con DLL.

Sembra che sostituisca la necessità di utilizzare le esportazioni esplicite all’interno del codice DLL (ad esempio, esplicito __declspec (dllexport)), tuttavia non sono in grado di generare un file lib quando non si utilizza ciò che crea problemi di linker in seguito quando si utilizza la DLL.

Quindi, come si usa .defs quando si collega con l’applicazione client, sostituiscono la necessità di usare un’intestazione o un file .lib?

La mia comprensione è che i file .def forniscono un’alternativa alla syntax __declspec (dllexport), con l’ulteriore vantaggio di poter specificare esplicitamente gli ordinali delle funzioni esportate. Questo può essere utile se si esportano alcune funzioni solo da ordinale, che non rivela tante informazioni sulla funzione stessa (ad esempio: molte delle funzioni di esportazione della DLL interna del sistema operativo solo da ordinale).

Vedi la pagina di riferimento .

Si noti che i nomi nel file .def devono corrispondere ai nomi nel binario. Quindi se usi C o C ++ con “extern” C “{…}”, i nomi non verranno alterati; in caso contrario è necessario utilizzare i nomi corretti per la versione specifica del compilatore utilizzato per generare la DLL. La funzione __declspec () fa tutto automaticamente.

Trovo che l’uso sia di __declspec (dllexport) sia del file .def sia utile per creare DLL portatili, ovvero DLL che possono essere chiamate da codice compilato con un compilatore diverso o con diverse impostazioni del compilatore.

Basta inserire __declspec (dllexport) nelle dichiarazioni delle funzioni perché tali funzioni vengano “esportate” dalla DLL (almeno su Windows) in modo che possano essere richiamate dall’esterno della DLL.

Tuttavia, aggiungendo alla build un file .def che elenca tutte le funzioni esportate, è ansible impedire ai compilatori Microsoft (ad esempio) di aggiungere una sottolineatura principale e le informazioni sulla larghezza del parametro finale al nome della funzione esportata (almeno se combinato con __stdcall direttiva, utile anche per la portabilità). Ad esempio la dichiarazione di funzione

void foo(int i); 

potrebbe finire per essere esportato come “_foo @ 4” se non si presta attenzione a chiamare la convenzione e l’uso del file .def.

Mantenere i nomi delle funzioni esportati nella tabella dei simboli liberi da tale decorazione dei nomi è molto utile quando si effettuano chiamate GetProcAddress () come parte del caricamento e dell’aghook in una DLL esplicitamente in fase di esecuzione. cioè per ottenere un puntatore alla funzione di cui sopra foo () (supponendo che sia stato esportato a tutti) in fase di runtime, idealmente vuoi solo chiamare:

 HANDLE dllHandle = LoadLibrary("mydll.dll"); void* fooFcnPtr = GetProcAddress(dllHandle, "foo"); 

Con un certo controllo caso di errore, ovviamente!

L’uso di un file .def più __stdcall, __declspec (dllexport) e extern “C” sulle dichiarazioni di funzione durante la creazione della DLL garantirà che il codice lato client sopra riportato funzioni per un’ampia gamma di compilatori e impostazioni del compilatore.

Per chi è interessato ancora … per essere in grado di collegarsi al file dll e def si richiede anche un file lib. In Windows questo può essere fatto dalla def usando lo strumento ‘LIB’. Vedi sotto per un esempio del modo in cui la linea di comando lo fa.

 lib /machine:i386 /def:sqlite3.def 

Spero che questo aiuti gli altri.

Non ho lavorato molto con le DLL, ma la mia comprensione è che per le funzioni C ++ esportate, si usa il “__declspec (dllexport)”, e per le funzioni C esportate si dovrebbe scrivere il file .def. Questo probabilmente perché le funzioni C ++ supportano l’overloading, ma le funzioni C no.

I file .DEF erano più comuni nelle windows a 16 bit dove di solito erano l’unico modo per specificare quali simboli dovevano essere esportati.

Inoltre, hanno fornito un mezzo per specificare le esportazioni per valore ordinale (@ 1, @ 2 ecc.) Anziché per nome. Questo metodo di ricerca dei simboli è stato utilizzato quando le prestazioni erano davvero importanti, come nei driver video.

La mia comprensione è che i file .def in realtà non specificano quale delle API debbano essere esportate. Contiene solo le apis esportate e i loro numeri ordinali. Se si desidera esportare effettivamente una particolare API, è necessario specificare __declspec (dllexport) nella definizione di api e __declspec (dllimport) nella dichiarazione.

Il vantaggio del file def è che, ti aiuta a mantenere la compatibilità con il backword con le dll già esistenti. cioè mantiene i numeri ordinali per l’apis. Supponiamo che tu aggiunga una nuova API nella DLL, quindi il linker guarda il tuo file .def genearà il numero ordinale per il ne wapi in modo tale che i numeri ordinali per le vecchie apis siano intatti.

Quindi, se il codice client utilizza l’ultima DLL, non infrange gli apis esistenti.