Domanda

Sono bloccato su una correzione per un'app Visual C++ 6 legacy.Nel sorgente DLL C++ ho inserito

extern "C" _declspec(dllexport) char* MyNewVariable = 0;

il che si traduce nella visualizzazione di MyNewVariable (piacevolmente non decorata) nella tabella di esportazione (come mostrato da dumpbin /exports blah.dll).Tuttavia, non riesco a capire come dichiarare la variabile in modo da potervi accedere in un file sorgente C.Ho provato varie cose, incluso

_declspec(dllimport) char* MyNewVariable;

ma questo mi dà solo un errore del linker:

simbolo esterno non risolto "__declspec(dllimport) char * MyNewVariable" (__imp_?MyNewVariable@@3PADA)

extern "C" _declspec(dllimport) char* MyNewVariable;

come suggerito da Tony (e come ho provato prima) si traduce in una decorazione diversa prevista, ma non l'ha ancora rimossa:

simbolo esterno non risolto __imp__MyNewVariable

Come scrivo la dichiarazione in modo che la variabile DLL C++ sia accessibile dall'app C?


La risposta

Come identificato da botismarius e altri (molte grazie a tutti), avevo bisogno di collegarmi al file .lib della DLL.Per evitare che il nome venisse alterato dovevo dichiararlo (nel sorgente C) senza decoratori, il che significa che dovevo usare il file .lib.

È stato utile?

Soluzione

è necessario collegarsi alla libreria generata dopo aver compilato la DLL.Nelle opzioni del linker del progetto, è necessario aggiungere il file .lib file.E sì, dovresti anche dichiarare la variabile come:

extern "C" { declspec(dllimport) char MyNewVariable; }

Altri suggerimenti

extern "C" è il modo in cui rimuovi la decorazione: dovrebbe funzionare utilizzando:

extern "C" declspec(dllimport) char MyNewVariable;

o se vuoi un'intestazione che possa essere utilizzata da C++ o C (con l'opzione /TC)

#ifdef __cplusplus
extern "C" {
#endif
declspec(dllimport) char MyNewVariable;
#ifdef __cplusplus
}
#endif

E, naturalmente, collegati alla libreria di importazione generata dalla DLL che esegue l'esportazione.

Non sono sicuro di chi abbia ridimensionato Botismarius, perché ha ragione.Il motivo è che il file .lib generato è la libreria di importazione con cui è semplice dichiarare semplicemente la variabile/funzione esterna __declspec(dllimport) e basta usarlo.La libreria di importazione automatizza semplicemente il necessario LoadLibrary() E GetProcAddress() chiamate.Senza di esso, è necessario chiamarli manualmente.

Hanno ragione entrambi.Il fatto descritto dal messaggio di errore __imp_?MyNewVariable@@3PADA significa che sta cercando il nome decorato, quindi è necessaria la "C" esterna.Tuttavia, il collegamento con la libreria di importazione lo è Anche necessario o riceverai semplicemente un errore di collegamento diverso.

@Graeme:Hai ragione anche su questo.Penso che il compilatore "C" utilizzato dall'OP non stia applicando lo standard C99, ma compilando come C++, alterando così i nomi.Un vero compilatore C non capirebbe la parte "C" del file extern "C" parola chiave.

Nel codice sorgente dll dovresti avere questa implementazione in modo che il file .lib esportazioni il simbolo:

extern "C" _declspec(dllexport) char* MyNewVariable = 0;

Il client c dovrebbe utilizzare a intestazione con questa dichiarazione in modo che il codice cliente lo faccia importare il simbolo:

extern "C" _declspec(dllimport) char* MyNewVariable;

Questa intestazione causerà un errore di compilazione se #include-ed nel codice sorgente della dll, quindi di solito viene inserita in un'intestazione di esportazione utilizzata solo per le funzioni esportate e solo dai client.

Se necessario, puoi anche creare un'intestazione "universale" che può essere inclusa ovunque e che assomigli a questa:

#ifdef __cplusplus
extern "C" {
#endif
#ifdef dll_source_file
#define EXPORTED declspec(dllexport) 
#else
#define EXPORTED declspec(dllimport) 
#endif dll_source_file
#ifdef __cplusplus
}
#endif

EXPORTED char* MyNewVariable;

Quindi il codice sorgente della dll è simile al seguente:

#define dll_source_code 
#include "universal_header.h"

EXPORTED char* MyNewVariable = 0;

E il client si presenta così:

#include "universal_header.h"
...
MyNewVariable = "Hello, world";

Se lo fai spesso, il mostro #ifdef in alto può andare in export_magic.h e universal_header.h diventa:

#include "export_magic.h"

EXPORTED char *MyNewVariable;

Non ho mai utilizzato _declspec(dllimport) durante la programmazione in Windows.Dovresti essere in grado di dichiarare semplicemente

extern "C" char* MyNewVariable;

e collegamento al file .libb creato durante la compilazione della DLL.

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