Allocation mémoire d'une structure passée en pointeur à une DLL C++

Résolu
Feanor06 Messages postés 34 Date d'inscription jeudi 18 février 2010 Statut Membre Dernière intervention 23 juillet 2010 - 25 mars 2010 à 17:06
BruNews Messages postés 21041 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019 - 26 mars 2010 à 19:46
Bonjour !

Bon, désolé mais je dois pas être dans le bon thème, mais j'en ai pas trouvé qui collait bien (style "truc de ouf" ).

J'ai un exe en vb.net (VS 2008 Express) et une DLL en C++ (Dev-C++).

Je passe à la librairie une structure qui doit être remplie par celle-ci.
Et forcement, ça ne fonctionne pas...

Exe :

Public Structure patch
Dim xc, yc, w, h As Integer
Dim r, g, b As Double
End Structure

Public tabp(144) As patch

Result_Geom = get_geom(tabp)

DLL :

extern "C" __declspec (dllexport) __stdcall int get_geom(struct patch * tab_p)
{
tab_p[0].yc = 69; //juste pour tester une ecriture
return tab_p[10].xc; // et une lecture...
}

La j'arrive bien à lire dans la structure, mais impossible d'écrire (value toujours à 0), par contre, pas d'erreur.

J'ai essayé ça aussi, et je pense que c'est la bonne écriture, mais ça ne marche pas non plus... (tentative de lecture/écriture en mémoire protégée)

extern "C" __declspec (dllexport) __stdcall int get_geom(struct patch * tab_p[])
{
(*tab_p[0]).yc = 69;
return (*tab_p[10]).xc;
}

Je pense que c'est un problème d'allocation mémoire, qu'il faudrait faire dans l'exe après la déclaration de la structure mais tout ce que j'ai essayé ne fonctionne pas en raison du type de data de celle-ci (pas un IntPtr, non Blittable...).

J'ai plus d'idée...

Merci à vous !!!

12 réponses

lesdis Messages postés 403 Date d'inscription mercredi 19 avril 2006 Statut Membre Dernière intervention 7 août 2020
26 mars 2010 à 10:17
Bonjour,

Effectivement, la structure n'était pas modifier.
Voici une solution qui fonctionne :
- On passe la variable par référence
- Le pointeur d'un tableau correspond à sa première occurrence.

Par contre, il y a un truc qui m'embête, c'est que si l'on dépasse les limites du tableau dans la dll, je ne reçois aucun message d'erreur


<Runtime.InteropServices.DllImport("maDLL.dll")> _
Private Shared Function Ouvrir(ByRef tab_patch() As patch) As Integer
End Function

Public tab_patch(144) As patch

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  Ouvrir(tab_patch(0))
  MessageBox.Show(tab_patch(10).xc, "Test", MessageBoxButtons.OK, MessageBoxIcon.None)
End Sub



struct patch {
int xc, yc, w, h;
double r, g, b;
};

int Ouvrir(struct patch * tab_p)
{
tab_p[0].yc = 69;
tab_p[10].xc=15;
return 1; 
}



Bonne Prog
3
Feanor06 Messages postés 34 Date d'inscription jeudi 18 février 2010 Statut Membre Dernière intervention 23 juillet 2010
25 mars 2010 à 17:08
Je précise que je déclare la structure de la même manière que dans l'exe en vb dans le .h de la DLL :

struct patch {
int xc, yc, w, h;
double r, g, b;
};

PLEASE HELP
0
lesdis Messages postés 403 Date d'inscription mercredi 19 avril 2006 Statut Membre Dernière intervention 7 août 2020
25 mars 2010 à 17:38
Bonjour,

Je viens de faire le test et tout fonctionne pour ma part,

j'ai repris le code vb sans y toucher :
 
<Runtime.InteropServices.DllImport("maDLL.dll")> _
Private Shared Function Ouvrir(ByVal toto() As patch) As Integer
End Function

Public toto(144) As patch

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  MsgBox(Ouvrir(toto))
End Sub


Et pour le code C(c'était plus rapide pour moi)
struct patch {
int xc, yc, w, h;
double r, g, b;
};

int Ouvrir(struct patch * tab_p)
{
tab_p[0].yc = 69; //juste pour tester une ecriture
tab_p[10].xc=15;
return tab_p[10].xc; // et une lecture... 
}



La boite de dialogue me ressort bien 15.
A voir si c'est un soucis de déclaration de fonction


Bonne Prog
0
BruNews Messages postés 21041 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
25 mars 2010 à 17:52
int Ouvrir(struct patch * tab_p)
{
tab_p[0].yc = 69; //juste pour tester une ecriture
tab_p[10].xc=15;
return tab_p[10].xc; // et une lecture...
}

Juste pour la précision:
un compilo C correct ne fait aucune lecture ici, la valeur 15 aura été mise dans EAX, ensuite EAX mis dans tab_p[10].xc et illico c'est "RET 4" pour retour chez l'appelant.

ciao...
BruNews, MVP VC++
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Feanor06 Messages postés 34 Date d'inscription jeudi 18 février 2010 Statut Membre Dernière intervention 23 juillet 2010
25 mars 2010 à 18:01
Et bien tout d'abord merci beaucoup à vous deux !

Ensuite, BruNews, pour bien comprendre, tu veux dire qu'en fait le compilo se souvient de l'affectation qu'il a fait juste au dessus et ne "s'embête" pas à lire dans la structure en affichant 15 ?

Ça expliquerai pourquoi ça fonctionne chez lesdis ? Qu'il n'aurait pas vraiment écrit dans la structure ?
Je cherche juste à comprendre, je ne mets pas en doute ce que tu dis lesdis.
0
BruNews Messages postés 21041 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
25 mars 2010 à 18:40
NON, on écrit bien dans la structure mais par le biais de EAX préalablement affecté, ainsi valeur de retour et affectation dans la structure ne sont codés (ASM par compilo C) qu'1 seule fois.
Un compilo C est un monstre d'optimisation.

ciao...
BruNews, MVP VC++
0
Feanor06 Messages postés 34 Date d'inscription jeudi 18 février 2010 Statut Membre Dernière intervention 23 juillet 2010
25 mars 2010 à 19:58
Ah ok, oui, je comprends.
Merci de la précision !

lesdis, je veux pas abuser mais pour être certain que ça fonctionne dans les 2 sens, peux-tu essayer, avec ton bout de code, de lire le 69 écrit dans yc sous vb, parce que le problème que j'ai, avec ces déclarations, c'est qu'en vb je vois que des 0 après la fonction.

Par contre avec la 2ème solution((*tab_p[0]).yc = 69;), j'ai une alerte de lecture/écriture en mémoire protégée.

Merci beaucoup et bonne soirée à tous !
0
lesdis Messages postés 403 Date d'inscription mercredi 19 avril 2006 Statut Membre Dernière intervention 7 août 2020
25 mars 2010 à 20:16
N'ayant pas VS chez moi, je verrais ca demain matin au boulot.


Bonne Prog
0
cs_Jack Messages postés 14007 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
25 mars 2010 à 20:22
Salut
Info à vérifier en .Net :
Sous VB6,
Dim xc, yc, w, h As Integer 
ne signifie pas que chaque élément sera dimensionné en Integer.
Seul h le sera, les précédent seront des Variant
-->
Dim xc As Integer, yc As Integer, w As Integer, h As Integer 

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
0
Feanor06 Messages postés 34 Date d'inscription jeudi 18 février 2010 Statut Membre Dernière intervention 23 juillet 2010
26 mars 2010 à 09:37
Merci de la proposition Jack mais en vb.net, le typage multiple fonctionne bien.

Et je confirme lesdis, ce que tu proposes fonctionne mais moi, je n'ai rien dans la structure coté VB, je pense que c'est pareil pour toi. Et je ne comprends toujours pas pourquoi...
0
Feanor06 Messages postés 34 Date d'inscription jeudi 18 février 2010 Statut Membre Dernière intervention 23 juillet 2010
26 mars 2010 à 10:45
Ok merci, c'est parfait !!!

Par contre (ça pourra servir à quelqu'un d'autre...), dans la déclaration de la fonction de la DLL sous VB, je pense qu'il faut enlever les parenthèses puisque tu ne passes qu'un élément :
Private Shared Function Ouvrir(ByRef tab_patch As patch)

Et bien en tous cas merci beaucoup pour ton aide !!!!

Bonne journée et bon week-end à tous !

PS : si quelqu'un peut un jour m'expliquer pourquoi ça ne fonctionnait pas avant et le coup du message d'erreur que soulève lesdis, je suis preneur.
0
BruNews Messages postés 21041 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
26 mars 2010 à 19:46
On n'a pas de message d'erreur tant qu'on écrit sur des octets de mémoire "writable".
Une DLL prenant un tableau à remplir doit toujours avoir un param 'count'. Il faut prendre exemple sur l'API Windows, c'est toujours ainsi.

ciao...
BruNews, MVP VC++
0