z_san
Messages postés80Date d'inscriptionjeudi 2 février 2006StatutMembreDernière intervention24 mai 2007
-
29 mai 2006 à 13:49
z_san
Messages postés80Date d'inscriptionjeudi 2 février 2006StatutMembreDernière intervention24 mai 2007
-
9 juin 2006 à 16:06
Voilà j'utilise une dll que j'ai développé en C, dans un programme C#.
Quand j'appel une fonction de la dll par DLLImport, au moment ou le programme passe sur l'appel de cette méthode, celà me génére une exception du type "Is not PInvoke compatible"
J'avoue en perdre mon latin, ai-je fait une fausse manip dans l'appel de la fonction
z_san
Messages postés80Date d'inscriptionjeudi 2 février 2006StatutMembreDernière intervention24 mai 2007 1 juin 2006 à 10:20
j'ai une autre question si je veux passer ma structure dans l'autre sens en utilisant une fonction de mise à jour des données de ma structure, par une fonction du type
void MajStruct(MaStruct struct);
sachant que ma struct en C# contient le InPtr qui corresponds à un pointeur sur une chaîne de caractère en C dans mon autre structure
Comment j'initialise mon Imptr pour que celà soit compris de m'autre côté ?
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 1 juin 2006 à 10:55
Peut être que ça marche mais je pense qu'il ya un problème avec le IntPtr, la chaine est allouée dans le code C mais je ne vois pas comment le CLR, peut la détruire dans le code C#, doit y'avoir un memory leak.
Par contre avec un tableau char de taille fixe dans la structure la je pense que ce sera plus simple, je peux essayer de te faire le code si tu veux..
z_san
Messages postés80Date d'inscriptionjeudi 2 février 2006StatutMembreDernière intervention24 mai 2007 7 juin 2006 à 11:41
PAr contre soucis que j'ai les données des structures se dégradent quand je lance la fonction, quand j'affiche les données de ma structure passées par le programme en C# à celui en cpp il affiche des choses farfelues ou la valeur de champ d'une autre structure ayant la même "structure de données"
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 7 juin 2006 à 14:20
Je ne sais pas, on a peut être mal agencé la structure entre le C et le C#. Comme ton programme manipule beaucoup de données en code managé et non managé je me demande si c'est pas mieux de travailler directement avec les pointeurs, completement en code unsafe et de laisser tomber le marshaling au moins on comprtends exectement ce qui se passe en mémoire et en plus ce sera plus rapide.
// CPP
typedef struct _MyStruct
{
int x;
int y;
} MyStruct;
// En C# on envoie un IntPtr ou MyStruct*
void FromCSharp( MyStruct* p )
{
if ( p != NULL )
{
p->x = 0;
p->y = 1;
}
}
// En C# on reçoit un IntPtr ou MyStruct*
MyStruct* ToCSharp( )
{
MyStruct* p = new MyStruct( );
p->x = 0;
p->y = 1;
return p;
}
// En C# on envoie un IntPtr ou MyStruct*
void FreeFromCSharp( MyStruct* p )
{
if ( p != NULL )
delete p;
}
unsafe void MyFunction1( )
{
// Alloue une structure dans la mémoire NON managée !!
IntPtr hGlobal = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( MyStruct ) ) );
MyStruct* p = ( MyStruct* )hGlobal;
p->X = 0;
p->Y = 0;
// On l'envoie vers le C.
FromCSharp( p );
// On la detruit.
Marshal.FreeHGlobal( hGlobal ); // la mémoire non managée est libérée.
}
unsafe void MyFunction2( )
{
// On récupère une structure allouée en C.
MyStruct* p = ToCSharp( );
p->X = 5;
p->Y = 8;
// On demande au C de la détruire.
// On pourrait la détruire depuis C#
// si c'était de la mémoire COM.
// allouée avec AllocCoTaskMem etc..
FreeFromCSharp( p ); // la mémoire non managée est libérée.
}
z_san
Messages postés80Date d'inscriptionjeudi 2 février 2006StatutMembreDernière intervention24 mai 2007 8 juin 2006 à 10:35
ok j'ai mis tout ça dans un projet d'essai j'ai un message d'erreur "Pointers and fixed size buffers may only be used in an unsafe context" et ceux à chaque fois que j'utilise la structure MyStruct p
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 8 juin 2006 à 18:11
"oui mais pour ma grosse structure contenant une structure et des enum je fais comment maintenant ?"
Je voulais te montrer le passage par pointeur sans utiliser le marshaleur mais c'est idiot j'ai fait l'exemple avec un pointeur sur une structure au lieu d'utiliser un IntPtr ou void* , du coups ça sert à rien tu te retrouves avec le même problème pour créer ta structure coté CSharp.. Ce que je voulais montrer avec cet exemple c'est qu'une fois que tu as un pointeur dans le code C# tu peux acceder à la mémoire non managée..
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 9 juin 2006 à 11:32
Non tout est dans le code précédent.. oublie l'autre exemple avec Function1 et Function2, c'était pour montrer le passage par pointeur ça marche bien mais c'est difficilement applicable dans ton cas, ça va compliquer les choses, je n'aurais pas du partir sur cette piste.
Il te suffit de faire un copier/coller du tout dernier code que je viens de te donner, et de remplir la méthode Fill comme tu le souhaite. La méthode Fill marche en entree/sortie. Tu peux par exemple afficher les champs avec une MessageBox puis les modifier. les changements seront visibles dans le code C# au retour de la fonction. Tester avec Dev-C++.
Non c'est pas la même chose moi je parle de #pragma pack qui permet de modifier l'alignement.