cs_cassiopee
Messages postés8Date d'inscriptionvendredi 11 janvier 2002StatutMembreDernière intervention11 octobre 2006
-
6 juil. 2006 à 17:41
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 2012
-
8 sept. 2006 à 04:34
D'abord bonjour a tous.
Ensuite... j'ai un probleme (eh oui c'est pour ca que j'écris ce message)
Voila je dois ecrire un programme en C#.NET qui utilise une DLL écrite en C++. J'ai trouvé qu'il fallait utiliser P/Invoke.
Ca marche bien sauf dans le cas d'une fonction ou plutot de plusieurs fonctions qui me retourne une structure contenant un tableau d'autre structure. Quand j'essaye d'executer cette methode, j'ai une erreur du type :
La signature du type de cette méthode n'est pas compatible avec PInvoke.
Pour un peu plus de détail, la fonction de ma DLL me retourne une structure du type :
struct listeTruc{
int nombre;
struct truc tab[];
}
J'ai donc défini ces 2 structures dans mon prog en .NET
Mais ca marche pas. Je pense que c'est parce qu'il s'agit d'un type un peu trop compliqué pour p/Invoke, mais je n'en suis pas sure.
Si vous pouviez me le confirmer...
Et si j'ai raison, et meme si j'ai tord, connaissez-vous une solution a mon probleme?
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 13 juil. 2006 à 04:28
Pour passer un tableau de structure :
[ StructLayout( LayoutKind.Sequential ) ]
private struct MyStruct
{
int x;
int y;
}
[ DllImport( "myLib.dll" ) ]
private static extern int MyFunc( [ In ] MyStruct[ ] myTab );
Ca c'est le marshalling par défaut, remplace [ In ] par [ In, Out ] pour avoir un tableau marshaller en entrée et en sortie. Mais n'oublie pas que si le tableau est alloué dans le code C il ne sera pas récupéré par le Garbage Collector.
// Un exemple ( C# ) :
// Implémente le code C pour qu'il renvoie la taille nécessaire si le tableau est null.
int size = MyFunc( null );
// On alloue le tableau managé à la bonne taille.
MyStruct[ ] tab = new MyStruct[ size ];
// On remplit le tableau
// le prototype doit être [ In, Out ]
MyFunc( tab );
cs_cassiopee
Messages postés8Date d'inscriptionvendredi 11 janvier 2002StatutMembreDernière intervention11 octobre 2006 7 juil. 2006 à 09:55
Merci pour le lien.
J'ai réussi à faire ce que je voulais. Ou presque...
Disons que j'arrive a passer dans ma structure principale un tableau de sous-structure. Par contre je suis obligé de définir la taille du tableau de sous-structure. Est qu'il y a un moyen de ne pas fixer cette taille?
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 8 juil. 2006 à 03:25
C'est un peu le problème qui c'est passé dans le lien précédent, et j'ai toujours pas de certitudes et toujours pas trouvé d'exemples sur le net. Si on ne connait pas le nombre d'éléments ça implique d'utiliser un pointeur pour le tableau de structures ( ou IntPtr ) mais si le tableau est alloué en C/C++ , comment le libérer en C#, il n y a pas d'opérateur delete en C#. ( si il est alloué avec CoTaskMemAlloc ont peut le libérer avec Marshal.FreeCoTaskMem du coté du code managé. )
Faudrait envisager un moyen de demander le nombres d'éléments au code C/C++ ( genre : getSize( ) ) puis allouer en C# un tableau de taille nécessaire, le fixer en mémoire ( mot clé : fixed ) puis le passer en IntPtr dans la structure. Comme le tableau à été alloué du coté du code managé il sera récupéré par le garbage collector.
Vous n’avez pas trouvé la réponse que vous recherchez ?
cs_cassiopee
Messages postés8Date d'inscriptionvendredi 11 janvier 2002StatutMembreDernière intervention11 octobre 2006 12 juil. 2006 à 15:33
Re-bonjour,
Voila, j'ai un autre pb.
J'ai dans ma DLL, j'ai une fonction qui prend en paramètre un pointeur sur un tableau de structure. J'avoue que j'ai du mal avec le marshalling. quelqu'un pourrait t'il m'aidé sur ce sujet.
Ma fonction a une signature (non managée) du type : void maFonction(struct test * )
Quelle doit-etre la signature de cette meme fonction en code managé? J'ai essayé avec un IntPtr mais j'arrive pas à récupérer les différents éléments de mon tableau. Si quelqu'un avait un exemple de code ca m'aiderai beaucoup.
cs_cassiopee
Messages postés8Date d'inscriptionvendredi 11 janvier 2002StatutMembreDernière intervention11 octobre 2006 12 juil. 2006 à 15:53
Juste une autre petite question. Est ce que ca serait plus facile si ma fonction dans la DLL retournait un pointeur sur le tableau de structure, ou le tableau lui-meme.
C'est a dire, si le prototype de la fonction est du style :
struct test maFonction()
ou struct test * maFonction().
Quelle-est la différence entre ces trois cas. Quelle solution me conseillez-vous?
cs_cassiopee
Messages postés8Date d'inscriptionvendredi 11 janvier 2002StatutMembreDernière intervention11 octobre 2006 6 sept. 2006 à 15:12
Eh oui, c'est encore moi... j'ai un autre petit soucis qui m'est apparu. Voila, en fait, j'ai dans une structure que je dois marshaller un tableau de chaine de caratères. Est-ce que c'est possible de marshaller ca?
Je m'explique. En C++ j'ai :
typedef struct FIELDSTRUCTURE
{
char id[SIZE_ID];
char label[SIZE_LABEL];
char dataType[SIZE_DATATYPE];
int position;
int update;
char parentFieldId[MAX_PARENT][SIZE_ID];
}FIELDSTRUCTURE;
En C# pour marshaller les premiere varaible de la strucutre, y a pas de pb mais pour le parentFieldId, j'ai un soucis.
Je sais marshaller un tableau :
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
Je sais marshaller une chaine de caractère :
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
Mais les deux en meme temps je sais pas.
// Tableau de bytes car char égale 2 bytes
// pour les tableaux fixes, peu importe
// le CharSet de la structure.
public fixed sbyte parentFieldId[ MAX_PARENT * SIZE_ID ];
}
Et pour le récupérer sous forme de tableau de chaines :
unsafe
{
sbyte* p = myStruct.parentFieldId;
string[ ] tab = new string[ MAX_PARENT ];
for ( int i = 0; i < MAX_PARENT; i++ )
tab[ i ] = new string( p + ( i * SIZE_ID ) );
}