Come esportare/importare una struttura in C da una DLL/ a di un’applicazione console tramite __declspec( dllexport/import )

Questa è la mia prima volta alle prese con le Dll. Di seguito la documentazione di MSDN ho creato un file di intestazione fooExports.h con le macro definite in base a una definizione del preprocessore:

#ifdef FOODLL_EXPORTS
    #define FOO_API __declspec( dllexport )
#else
    #define FOO_API __declspec( dllimport )

La mia intenzione era di utilizzare questa intestazione sia nella mia DLL attuazione e nell’applicazione console. Finora l’importazione e l’esportazione delle funzioni funziona bene. Il problema vetri quando si tenta di esportare un già definito una struttura che mi serve come parametro per una delle funzioni esportate. Per esempio, nel suddetto file di intestazione dichiaro FOO_API void foo( FooParams *args ) e args è una struttura definita come segue:

typedef struct FooParams
{
    char *a;
    char *b;
    void *whatever; //some other type
} FooParams;

Questa struttura deve essere definito in pippo.h piuttosto che in fooExports.h. C’è un modo per esportare questa struttura senza prendere fuori di esso originale del file di intestazione (tenendo in considerazione che voglio mantenere le esportazioni/importazioni centralizzato in fooExports.h).
Che cosa sarebbe un approccio migliore per fare questo? La DLL è tutto C, come pure l’applicazione client che utilizza.

Non tipi di esportazione, di esportazione linker simboli.
ti dispiacerebbe espansione?
Non è chiaro perché hai usato due .h file o perché proprio non dichiarare il tipo di argomento per foo(). Non c’è niente da esportare nella struttura, non è necessario alcun codice. Il modo più semplice per evitare il dilemma è quello di utilizzare solo uno .h file e il gioco è fatto.
Ho fissato il tipo di parametro, come hai suggerito. Il motivo per cui non voglio solo un file di intestazione è perché l’esportazione di un file di intestazione deve essere condivisa con il client e il DLL e non voglio esporre la dichiarazione di tutti i miei strutture in intestazione.
Si desidera che il codice del client per vedere __declspec(dllimport) e FooParams. Quindi tutto ciò che hai postato finora appartiene .h file. Se si dispone di altri .h i file che sono specifici per l’attuazione poi basta #includere nella vostra .i file cpp.

OriginaleL’autore wotann07 | 2013-03-11

One Reply
  1. 10

    Solo se uso il client potrà mai avere per FooParams è quello di ottenere i puntatori ad esso restituito dalle funzioni di DLL e di trasmettere tali puntatori ad altre funzioni di DLL, si può fare un “opaco” tipo: Mettere

    typedef struct FooParams FooParams;

    in fooExports.h. Il FOO_API macro non appartiene a quella dichiarazione. Opaco tipo indica il codice del client, non è possibile:

    • Creare tutte le variabili di tipo FooParams (ma FooParams * ptr = NULL; è ok).
    • Fare nulla con qualsiasi membro del FooParams.
    • Trovare sizeof(FooParams) – e, pertanto, non può essere correttamente malloc spazio per uno o più FooParams oggetti.

    Non è possibile #define macro visibile il client che fare una di queste. Così la DLL avrebbe bisogno di avere uno o più “costruttore” o “fabbrica” di funzioni, forse qualcosa di simile

    FOO_API FooParams* CreateFooParams(const char * input);

    È anche buona pratica per definire una corrispondenza “distruttore” funzione come

    FOO_API void DestroyFooParams(FooParams * p);

    anche se la definizione è semplice come { free(p); }, perché a volte ci sono problemi se la memoria allocata all’interno di una DLL viene liberata dal codice al di fuori di essa o viceversa (perché non tutte le Finestre di codice utilizza identiche definizioni di malloc e free).

    Se tutto questo è troppo estremo, l’unica altra opzione è quella di mettere o #include il struct definizione nel esportati in file di intestazione e di renderlo visibile ai clienti. Senza che, ogni tentativo di fare qualcosa per un FooParams, altri di passaggio di puntatori in giro, è impossibile, perché il compilatore non conosce ciò che è in un FooParams. Il compilatore (rispetto al linker) prende le informazioni solo da riga di comando argomenti e #include-d file, non da librerie o Dll.

    vi ringrazio tanto. questa è una grande risposta!!! In attesa di una risposta che mi ha intuitivamente l’approccio di including mio intestazioni con la struttura definizioni nel client. Voleva solo assicurarsi che non c’era altro modo. E, come hai appena spiegato, non c’è per quello che devo fare. grazie ancora per il tuo tempo!

    OriginaleL’autore aschepler

Lascia un commento