Interopérabilité: Structure

Résolu
Tuizi Messages postés 144 Date d'inscription samedi 21 octobre 2000 Statut Membre Dernière intervention 7 mai 2009 - 18 avril 2007 à 11:06
Tuizi Messages postés 144 Date d'inscription samedi 21 octobre 2000 Statut Membre Dernière intervention 7 mai 2009 - 19 avril 2007 à 13:18
Bonjour,

Voila en C++ j'ai une DLL que j'utilise sans problème, et j'aimerai l'utiliser sur un programme C#, tout marche bien, les dllImport fonctionnent à merveille, mais je suis tomber sur une structure où ça coince:

typedef struct
{
    unsigned short  wHandleMsg;
    unsigned long   dwIdent; 
    tCanTypeId      eTypeId;    
    unsigned long   dwMask;    
    tCanService     eService;         
    unsigned long   lPeriod;            
    unsigned long   dwReserved1;        
    unsigned long   dwReserved2;       
    unsigned short  wDataLen;           
    unsigned char   bData[CAN_MAX_DATA];
} tCanMsg;

Que j'ai donc transformer en C# par:

public
struct
CanMsg
{

   public
UInt16 wHandleMsg; 
   p
ublic
UInt32 dwIdent; 

   public
CanTypeId eTypeId; 

   public
UInt32 dwMask; 

   public
CanService eService; 

   public
UInt32 lPeriod; 

   public
UInt32 dwReserved1; 

   public
UInt16 wDataLen; 

   public
byte[] bData;
};
Voyez vous une erreur? les CanTypeId et CanService sont de simple enum!

Car mon erreur vient du faite que le fonction qui utilise cette structure me dit qu'il y a une erreur de paramètre sur dwIdent

Tuizi

23 réponses

Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
18 avril 2007 à 16:05
Comme ça :

[ StructLayout( LayoutKind.Sequential, Pack = 2 ) ]

Reste le problème du tableau, car à mon avis tu t'attends à un tableau de taille :

sizeof( char ) * CAN_MAX_DATA

ce qui n'est pas le cas pour le moment, ce n'est pas un tableau inline dans la struct que tu as pour le moment mais un pointeur.
3
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
18 avril 2007 à 11:29
Peut-être un System.UInt64 plutôt qu'un UInt32 ?












<hr />
-Blog-
0
sebmafate Messages postés 4936 Date d'inscription lundi 17 février 2003 Statut Membre Dernière intervention 14 février 2014 37
18 avril 2007 à 11:30
non... moi, je verrai bien :

[StructLayout(LayoutKind.Sequential)]
public struct CanMsg
{
   public Int16 wHandleMsg; 
   public Int32 dwIdent; 
   public CanTypeId eTypeId; 
   public Int32 dwMask; 
   public CanService eService; 
   public Int32 lPeriod; 
   public Int32 dwReserved1; 
   public Int16 wDataLen; 
   public byte[] bData;
};

Sébastien FERRAND (blog)
Consultant Indépendant
[Microsoft Visual C# MVP]
0
Tuizi Messages postés 144 Date d'inscription samedi 21 octobre 2000 Statut Membre Dernière intervention 7 mai 2009
18 avril 2007 à 12:14
Bidou> Non, je pense pas car ça va changer considérablement la taille de la variable, on va passer d'un 32 bits à du 64 bits
sebmafate> Non, ça n'a rien changé à mon problème

Je comprends pas pouquoi il ne veut pas de ma structure elle a la meme taille pourtant!

Tuizi
0

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

Posez votre question
Tuizi Messages postés 144 Date d'inscription samedi 21 octobre 2000 Statut Membre Dernière intervention 7 mai 2009
18 avril 2007 à 12:54
Un enum en C# ou C++ fait la même taille?

Tuizi
0
2IZI4U Messages postés 9 Date d'inscription mardi 8 novembre 2011 Statut Membre Dernière intervention 6 mai 2007
18 avril 2007 à 13:03
nan en c# les struct sont très limités je me souviens plus de la taille.
Pour palier fait une classe avec des propriétés et des accesseurs.
0
sebmafate Messages postés 4936 Date d'inscription lundi 17 février 2003 Statut Membre Dernière intervention 14 février 2014 37
18 avril 2007 à 13:09
un enum en C# dérive pas défaut de System.Int32...

les structures C# ne sont pas si limitées que ca... il ne faut pas abuser !
voir : http://msdn2.microsoft.com/fr-fr/library/ah19swz4(VS.80).aspx

Sébastien FERRAND (blog)
Consultant Indépendant
[Microsoft Visual C# MVP]
0
sebmafate Messages postés 4936 Date d'inscription lundi 17 février 2003 Statut Membre Dernière intervention 14 février 2014 37
18 avril 2007 à 13:13
arf... j'avais mal lu la struct c++

[StructLayout(LayoutKind.Sequential)]
public struct CanMsg
{
   public UInt16 wHandleMsg; 
   public UInt32 dwIdent; 
   public CanTypeId eTypeId; 
   public UInt32 dwMask; 
   public CanService eService; 
   public UInt32 lPeriod; 
   public UInt32 dwReserved1; 
   public UInt16 wDataLen; 
   public byte[] bData;
};

Sébastien FERRAND (blog)
Consultant Indépendant
[Microsoft Visual C# MVP]
0
Tuizi Messages postés 144 Date d'inscription samedi 21 octobre 2000 Statut Membre Dernière intervention 7 mai 2009
18 avril 2007 à 14:20
sebmafate> Oui donc on est bien d'accord sur la structure en C#
Mais ça ne résoud toujours pas le problème.
J'ai fais des test est lorsque CanTypeId vaut la valeur 1, la fonction me retourne l'erreur: Erreur de paramètre, eTypeID ne peut pas être 65535 et lorsque CanTypeID vaut 0, ça me dit que j'ai une erreur sur l'identifient dwIdent.
Casse tête chinois!

Tuizi
0
sebmafate Messages postés 4936 Date d'inscription lundi 17 février 2003 Statut Membre Dernière intervention 14 février 2014 37
18 avril 2007 à 14:24
à la place de tes enums met un Int16 pour voir.

et surtout n'oublie pas l'attribut avant la déclaration de la structure.

Sébastien FERRAND (blog)
Consultant Indépendant
[Microsoft Visual C# MVP]
0
Tuizi Messages postés 144 Date d'inscription samedi 21 octobre 2000 Statut Membre Dernière intervention 7 mai 2009
18 avril 2007 à 14:37
ça n'a rien changé, que ce soit avec des Int16, UInt16, Int32 ou encore UInt32

Tuizi
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
18 avril 2007 à 14:58
Salut, il est clair que les structures sont justement beaucoup moins limitées que les classes quand il s'agit d'interop. Là je vois 2 problèmes dans ta struct.. c'est pas un type blittable, bData est une référence vers un tableau qui pointe dans le tas, bData fait 32 bits ou 64 bits selon l'architecture du processeur et si tu utilises les pointeurs sur cette struct attention tu as un alignement sur dwIdent, ç-à-d que dwIdent se trouve à l'octet 4.
0
Tuizi Messages postés 144 Date d'inscription samedi 21 octobre 2000 Statut Membre Dernière intervention 7 mai 2009
18 avril 2007 à 15:01
Lutinore> Wow j'ai peur de ne pas avoir tout compris
Qu'appel tu un alignement sur dwIdent?

Tuizi
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
18 avril 2007 à 15:23
Un type de taille n est positionner à une adresse multiple de n. wHandleMsg est un ushort, 2 octets.. et donc tu t'attends à trouver dwIdent 2 octets plus loin alors qu'en réalité il est 4 octets plus loin. Normalement pas de problème entre C++ et C# sauf si le code C++ utilise le #pragma pack( ) ?? , si c'est le cas, corrige la struct C# avec le champ Pack de StructLayout. Corrige aussi le tableau.
0
Tuizi Messages postés 144 Date d'inscription samedi 21 octobre 2000 Statut Membre Dernière intervention 7 mai 2009
18 avril 2007 à 15:50
Wow bien vu en effet il y a #pragma

pack(
push,2)  // 2-byte alignment: MSVC & Borland
dans le code C++.

ça marche comment le champ Pack de StructLayout?

Tuizi
0
Tuizi Messages postés 144 Date d'inscription samedi 21 octobre 2000 Statut Membre Dernière intervention 7 mai 2009
18 avril 2007 à 16:33
Ok merci pour le pack, ça a changer que mon application plante maintenant, mais c'est déja mieux!
Pour le tableau lors de l'utilisation je fais simplement un bData = new byte[8], ça ne va pas?

Tuizi
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
18 avril 2007 à 16:55
non, c'est un vrai tableau de byte que tu veux, pas une une chaine de caractères ?

[ MarshalAs( UnmanagedType.ByValArray, SizeConst = CAN_MAX_DATA )]
public byte[ ] bData; // ou un tableau fixe.

Pour les performances un tableau fixe c'est mieux mais ça oblige d'utiliser du code unsafe.
0
Tuizi Messages postés 144 Date d'inscription samedi 21 octobre 2000 Statut Membre Dernière intervention 7 mai 2009
18 avril 2007 à 18:50
Oui c'est bien un vrai tableau de byte que je veux.

Par contre je ne comprend pas le [MarshalAs...] car dans le code je serais tout de meme obligé de faire:
bData = new byte[taille];

Tuizi
0
Tuizi Messages postés 144 Date d'inscription samedi 21 octobre 2000 Statut Membre Dernière intervention 7 mai 2009
18 avril 2007 à 19:09
 498040 Lutinore> Un grand merci en tout cas car la fonction qui utilise ma structure marche parfaitement

Par contre toujours ce problème avec ce tableau si je met:
[ MarshalAs( UnmanagedType.ByValArray, SizeConst = CAN_MAX_DATA )]

je suis obligé de déclarer un tableau de CAN_MAX_DATA

Tuizi
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
18 avril 2007 à 19:12
Non c'est un tableau de taille fixe de sizeof( char ) * CAN_MAX_DATA, il ne faut pas l'allouer. Compare la taille avec et sans l'attriut MarshalAs.

Marshal.SizeOf( typeof( CanMsg ) );
0
Rejoignez-nous