Passage d’une structure à l’API C ++ à l’aide de Marshal.StructureToPtr en C #

J’utilise une API écrite en C ++ dans mon code (écriture en C #). L’API nécessite un paramètre en tant que pointeur sur la structure. La structure est composée de “Int” et de tableaux de caractères: par exemple

unsafe public struct ToBePassed { Int32 Num1; Int32 Num2; Char[] Data; // or fixed Char Data[255]; } 

Je ne peux pas passer directement le pointeur de structure à l’API car, dans ce cas, le message d’erreur suivant s’affiche: “Les pointeurs ne peuvent pas référencer les structures Marshaled”. Le code est compilé avec succès, mais cette erreur survient lorsque j’exécute (débogue) le code

Maintenant, j’ai deux options: 1ère: – Structure de passage par référence: je veux demander si une API nécessitant un pointeur de structure peut recevoir l’adresse lorsque je passe la structure par référence. Notez que l’API renverra les données dans “Char [] Data”.

2ème: – Utilisation de Marshal.StructureToPtr: Ceci convertira la structure du pointeur en IntPtr. Encore une fois, le doute est identique, cette API le recevra-t-elle correctement?

Merci pour votre temps!

Cordialement, Swanand

Si cela ne nécessite qu’un pointeur, vous pouvez allouer de la mémoire non gérée, organiser la structure dans la mémoire et transmettre ce pointeur à votre fonction. Ensuite, vous pourrez ensuite revenir à la structure (si vous le souhaitez) et libérer la mémoire. Avant de rassembler quoi que ce soit, vous devez définir correctement la structure. Quelque chose comme ça:

 [StructLayout( LayoutKind.Sequential, //must specify a layout CharSet = CharSet.Ansi)] //if you intend to use char public struct ToBePassed { public Int32 Num1; public Int32 Num2; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)] public Char[] Data; //specify the size using MarshalAs } [DllImport("...")] public static extern void APICall(IntPtr argPtr); public static void CallFunction(ToBePassed managedObj) { IntPtr unmanagedAddr = Marshal.AllocHGlobal(Marshal.SizeOf(managedObj)); Marshal.StructureToPtr(managedObj, unmanagedAddr, true); APICall(unmanagedAddr); Marshal.PtrToStructure(unmanagedAddr, managedObj); Marshal.FreeHGlobal(unmanagedAddr); unmanagedAddr = IntPtr.Zero; } 

[modifier]
Pour simuler des tableaux de longueur variable, allouez de la mémoire non gérée dans la structure et initialisez-la comme d’habitude.

 [StructLayout(LayoutKind.Sequential)] public struct SomeStruct { public Int32 X; public Int32 Y; } [StructLayout(LayoutKind.Sequential)] public struct VLA { public Int32 intArrayLength; public Int32 SomeStructArrayLength; public IntPtr intArray; public IntPtr SomeStructArray; } public static VLA CreateVLA(int[] intArray, SomeStruct[] SomeStructArray) { var vla = new VLA() { intArrayLength = intArray.Length, SomeStructArrayLength = SomeStructArray.Length, intArray = Marshal.AllocHGlobal(intArray.Length * Marshal.SizeOf(typeof(int))), SomeStructArray = Marshal.AllocHGlobal(SomeStructArray.Length * Marshal.SizeOf(typeof(SomeStruct))), }; Marshal.Copy(intArray, 0, vla.intArray, intArray.Length); //there's no overload to copy arbitrary arrays, do it manually for (int i = 0; i < SomeStructArray.Length; i++) { Marshal.StructureToPtr( SomeStructArray[i], vla.SomeStructArray + i * Marshal.SizeOf(typeof(SomeStruct)), true); } return vla; }