juin
2007
Suite à mon billet d’interopérabilité pour marshaller des structures natives, on va compliquer un peu la structure pour voir différents scénarios d’interopérabilité.
Prenons les structures suivantes :
int telfixe;
int telPort;
} MASTRUCTURETEL;
typedef struct {
int monAge;
int maTaille;
char *nom;
MASTRUCTURETEL structTel;
wchar_t *prenom;
} MASTRUCTURE;
On a donc une structure qui contient des entiers, une chaine (char *), une autre chaine (wchar_t *) et une structure qui contient elle même des entiers.
et maintenant, la fonction qui remplie la structure et retourne un pointeur.
{
MASTRUCTURE *maStruct = new MASTRUCTURE;
maStruct->maTaille = 185;
maStruct->monAge = 27;
maStruct->nom = new char[20];
maStruct->prenom = new wchar_t[20];
strcpy_s(maStruct->nom, 20, "pyright");
wcscpy_s(maStruct->prenom, 20, L"nico");
maStruct->structTel.telfixe = 123;
maStruct->structTel.telPort = 456;
return maStruct;
}
Reste maintenant à mapper cette structure un peu plus complexe en C# :
public class MaStructCSharp
{
public Int32 monAge;
public Int32 maTaille;
public IntPtr nom;
public MaStructCSharpTel maStructTel;
public IntPtr prenom;
}
[StructLayout(LayoutKind.Sequential)]
public class MaStructCSharpTel
{
public Int32 telFixe;
public Int32 telPort;
}
Finalement, ce n’est pas si compliqué, les entiers deviennent des Int32, les chaines deviennent des IntPtr et la sous-structure une classe.
On reprend le même principe pour remplir la classe avec le pointeur sur la structure :
MaStructCSharp maStructureCSharp = new MaStructCSharp();
Marshal.PtrToStructure(maStructureCUnmanaged, maStructureCSharp);
Console.WriteLine(maStructureCSharp.monAge);
Console.WriteLine(maStructureCSharp.maTaille);
Console.WriteLine(maStructureCSharp.maStructTel.telFixe);
Console.WriteLine(maStructureCSharp.maStructTel.telPort);
Notez que pour la sous-structure, il n’y a rien de particulier à faire.
Viennent maintenant les chaines, on va utiliser des méthodes de la classe Marshal pour les convertir :
Console.WriteLine(nom);
string prenom = Marshal.PtrToStringUni(maStructureCSharp.prenom);
Console.WriteLine(prenom);
PtrToStringAnsi pour convertir le char * et PtrToStringUni pour convertir le wchar_t *.
Assez simple globalement, mais les conversions de chaines sont assez lourdes. On est obligé de passer par un pointeur puis de le convertir, en utilisant une autre variable.
N’y aurait-il pas un moyen d’avoir directement des chaines C# dans notre structure plutot que des pointeurs et d’être obligé de convertir ?
Bien sur que si, la classe de marshal propose des attributs pour effectuer directement des opérations de marshaling sur des types qui ont un équivalent simple en C#.
Par exemple pour des chaines wchar_t *, on aura la strucure C :
wchar_t *nom;
wchar_t *prenom;
} MASTRUCTURE;
dont l’équivalent sera
public class MaStructCSharp
{
[MarshalAs(UnmanagedType.LPWStr)]
public string nom;
[MarshalAs(UnmanagedType.LPWStr)]
public string prenom;
}
On déclare directement des string et on utilise l’attribut MarshalAs et on précise le type, ici on va utiliser le paramètre UnmanagedType.LPWStr.
On pourra désormais récupérer les noms et prénoms ainsi :
MaStructCSharp maStructureCSharp = new MaStructCSharp();
Marshal.PtrToStructure(maStructureCUnmanaged, maStructureCSharp);
Console.WriteLine(maStructureCSharp.nom);
Console.WriteLine(maStructureCSharp.prenom);
Le code s’en trouve clarifié.
Voilà pour ces concepts d’interopérabilité
Commentaires récents
- [Tests] Arrange Act Assert, une traduction ? dans
- [UnitTest][C#] Tester une méthode privée dans
- Récupérer une valeur d’un contrôle depuis une autre Form / inclusions croisées et déclaration anticipée dans
- Tutoriel : Utiliser la ListBox et l’Isolated Storage dans vos applications Windows Phone 7 avec Silverlight dans
- Tutoriel : Utiliser la ListBox et l’Isolated Storage dans vos applications Windows Phone 7 avec Silverlight dans
Archives
- janvier 2013
- avril 2012
- janvier 2012
- juin 2011
- janvier 2011
- décembre 2010
- novembre 2010
- septembre 2010
- juin 2010
- mars 2010
- février 2010
- janvier 2010
- décembre 2009
- novembre 2009
- octobre 2009
- septembre 2009
- août 2009
- juillet 2009
- mai 2009
- avril 2009
- mars 2009
- janvier 2009
- décembre 2008
- novembre 2008
- octobre 2008
- septembre 2008
- août 2008
- juillet 2008
- juin 2008
- mai 2008
- avril 2008
- mars 2008
- février 2008
- janvier 2008
- décembre 2007
- novembre 2007
- octobre 2007
- septembre 2007
- août 2007
- juillet 2007
- juin 2007
- mai 2007