Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

peut on exporter une structure définie dans une DLL?

4 réponses
Avatar
giova
plus précisement j'ai définie une structure dans ma dll, et déclaré un
tableau de cette structure. Tout ceci n'est pas exporté car je ne veux
pas que l'on puisse modifier le contenu de l'exterieur.


je veux donc exporter une fonction qui :
1) alloue dynamiquement dans le tableau une "instance" de cette
structure (malloc)
2) qui retourne l'adresse de ce tableau.

voici donc a quoi ressemble mon header :


Code :


struct test
{
char* nom;
int nombre;
};

extern "C" test* __declspec(dllexport) _stdcall Test(void);





mais le compilateur semble ne pas apprecier que je retourne un poiteur
de type test puisqu'il me dit ceci :

warning C4518: '__declspec(dllexport ) ' : classe de stockage ou
spécificateur(s) de type inattendu(es) ; ignoré(es)

du coup je me demande si c'est possible ou si c'est moi qui m'y prends mal.

quelqu'un a une idée sur la question?

PS: ma dll doit exporter les fonctions pour du C d'où le extern "C"

4 réponses

Avatar
Arnaud Debaene
giova wrote:
plus précisement j'ai définie une structure dans ma dll, et déclaré un
tableau de cette structure. Tout ceci n'est pas exporté car je ne veux
pas que l'on puisse modifier le contenu de l'exterieur.


je veux donc exporter une fonction qui :
1) alloue dynamiquement dans le tableau une "instance" de cette
structure (malloc)
2) qui retourne l'adresse de ce tableau.

voici donc a quoi ressemble mon header :


Code :


struct test
{
char* nom;
int nombre;
};

extern "C" test* __declspec(dllexport) _stdcall Test(void);





mais le compilateur semble ne pas apprecier que je retourne un poiteur
de type test puisqu'il me dit ceci :

warning C4518: '__declspec(dllexport ) ' : classe de stockage ou
spécificateur(s) de type inattendu(es) ; ignoré(es)



Le declspec doit être avant le type de retour de la fonction (avant le
"declarator" pour être précis) :
extern "C" __declspec(dllexport) test* WINAPI Test(void);
(Ont a généralement tendance à remplacer _stdcall par WINAPI pour facilier
le portage à d'autres compilos - au fait ca n'a rien d'obligatoire
d'exporter des fonctions en stdcall).

Cependant, ta solution laisse "test" accessible au code client.

du coup je me demande si c'est possible ou si c'est moi qui m'y
prends mal.


Plusieurs solutions :

- Le client a besoin de savoir ce qu'est un "test" (pour appeler une méthode
dessus, etc...). Dans ce cas test doit être déclarée et définie dans le code
client (dans le header). C'est ce que tu fais actuellement.

- Tu te contentes de faire une "forward déclaration" de test. Dans ce cas,
to client peut manipuler des test* mais pas les déréférencer et accêder à
ces données membres.
/*
solution macro "standard" pour avoir un seul header pour la DLL et le client
qui l'utilise - compiler la DLL en définissant MADLLEXORT
*/
#ifdef MA_DLL
#define MADLLEXORT __declspec(dllexport) _stdcall
#else
#define MADLLEXORT __declspec(dllimport) _stdcall

extern struct test; //forward declartion de la classe
test* MADLLEXORT Test(void);

- Si tu veux que ta structure soit vraiment opaque, tu retournes un "handle"
(en fait un void*) : comme çà, le client ne peut absolument pas manipuler le
type des infos retournées.
#ifdef MA_DLL
#define MADLLEXORT __declspec(dllexport) _stdcall
#else
#define MADLLEXORT __declspec(dllimport) _stdcall
typedef void* myhandle;
extern "C" myhandle MADLLEXPORT Test(void);

Arnaud
Avatar
halfwolf
Salut,

giova wrote in message news:<408d843c$0$19487$...
struct test
{
char* nom;
int nombre;
};

extern "C" test* __declspec(dllexport) _stdcall Test(void);





mais le compilateur semble ne pas apprecier que je retourne un poiteur
de type test puisqu'il me dit ceci :

warning C4518: '__declspec(dllexport ) ' : classe de stockage ou
spécificateur(s) de type inattendu(es) ; ignoré(es)



Je ne m'y connais pas en DLL, mais il y a un problème en C : le type
test n'est pas défini.

Soit tu définis le type test de la façon suivante :
typedef struct
{
char* nom;
int nombre;
} test;

Soit ta fonction ne retourne pas test* mais struct test* :
extern "C" struct test* __declspec(dllexport) _stdcall Test(void);

En espérant que ça t'aidera.

HalfWolf
Avatar
giova
Merci Arnaud.

BOn je n'ai pas tout compris (normal , je débute), mais en tout cas le
fait de mettre Le declspec avant le type de retour de la fonction , fait
que ca fontionne parfaitement.

merci encore.

Arnaud Debaene wrote:

giova wrote:

plus précisement j'ai définie une structure dans ma dll, et déclaré un
tableau de cette structure. Tout ceci n'est pas exporté car je ne veux
pas que l'on puisse modifier le contenu de l'exterieur.


je veux donc exporter une fonction qui :
1) alloue dynamiquement dans le tableau une "instance" de cette
structure (malloc)
2) qui retourne l'adresse de ce tableau.

voici donc a quoi ressemble mon header :


Code :


struct test
{
char* nom;
int nombre;
};

extern "C" test* __declspec(dllexport) _stdcall Test(void);





mais le compilateur semble ne pas apprecier que je retourne un poiteur
de type test puisqu'il me dit ceci :

warning C4518: '__declspec(dllexport ) ' : classe de stockage ou
spécificateur(s) de type inattendu(es) ; ignoré(es)




Le declspec doit être avant le type de retour de la fonction (avant le
"declarator" pour être précis) :
extern "C" __declspec(dllexport) test* WINAPI Test(void);
(Ont a généralement tendance à remplacer _stdcall par WINAPI pour facilier
le portage à d'autres compilos - au fait ca n'a rien d'obligatoire
d'exporter des fonctions en stdcall).

Cependant, ta solution laisse "test" accessible au code client.


du coup je me demande si c'est possible ou si c'est moi qui m'y
prends mal.



Plusieurs solutions :

- Le client a besoin de savoir ce qu'est un "test" (pour appeler une méthode
dessus, etc...). Dans ce cas test doit être déclarée et définie dans le code
client (dans le header). C'est ce que tu fais actuellement.

- Tu te contentes de faire une "forward déclaration" de test. Dans ce cas,
to client peut manipuler des test* mais pas les déréférencer et accêder à
ces données membres.
/*
solution macro "standard" pour avoir un seul header pour la DLL et le client
qui l'utilise - compiler la DLL en définissant MADLLEXORT
*/
#ifdef MA_DLL
#define MADLLEXORT __declspec(dllexport) _stdcall
#else
#define MADLLEXORT __declspec(dllimport) _stdcall

extern struct test; //forward declartion de la classe
test* MADLLEXORT Test(void);

- Si tu veux que ta structure soit vraiment opaque, tu retournes un "handle"
(en fait un void*) : comme çà, le client ne peut absolument pas manipuler le
type des infos retournées.
#ifdef MA_DLL
#define MADLLEXORT __declspec(dllexport) _stdcall
#else
#define MADLLEXORT __declspec(dllimport) _stdcall
typedef void* myhandle;
extern "C" myhandle MADLLEXPORT Test(void);

Arnaud




Avatar
giova
et bien en fait je fait une "instance" de la structure en global dans le
cpp de ma dll, et ma fonction sort l'adresse de ce dernier, ce qui fait
que dans mon main je fais un :

struct test toto;
toto=Test();

;)

biensur j'ai egallement fait une fonction qui libere la mémoire par la
suite.

HalfWolf wrote:

Salut,

giova wrote in message news:<408d843c$0$19487$...

struct test
{
char* nom;
int nombre;
};

extern "C" test* __declspec(dllexport) _stdcall Test(void);





mais le compilateur semble ne pas apprecier que je retourne un poiteur
de type test puisqu'il me dit ceci :

warning C4518: '__declspec(dllexport ) ' : classe de stockage ou
spécificateur(s) de type inattendu(es) ; ignoré(es)




Je ne m'y connais pas en DLL, mais il y a un problème en C : le type
test n'est pas défini.

Soit tu définis le type test de la façon suivante :
typedef struct
{
char* nom;
int nombre;
} test;

Soit ta fonction ne retourne pas test* mais struct test* :
extern "C" struct test* __declspec(dllexport) _stdcall Test(void);

En espérant que ça t'aidera.

HalfWolf