2010-07-09 8 views
2

J'essaie de passer un tableau d'objets de C# à C++ non géré, et rien ne semble fonctionner.Comment passer un tableau d'objets en code non managé?

Le compilateur ne me laissera pas prétendre que le tableau est un IntPtr. Casting le tableau à un IntPtr ne fonctionne pas. J'ai essayé de transmettre l'adresse des données épinglées, mais cela n'a pas fonctionné non plus.

J'ai juste besoin de passer un pointeur au début du tableau, et cela s'avère incroyablement difficile.

Des suggestions ou des liens? Merci!

+0

Comment vous attendez-vous à voir ce tableau à partir d'un code non géré (c'est-à-dire quel sera le type d'élément)? –

+0

J'ai (j'espère) la même définition d'objet sur les côtés C# et C++. La fonction appelée a un pointeur sur ce type en tant que paramètre. – user20493

+0

Vous voulez dire une définition de classe C++? Cela ne fonctionne pas comme ça. La mise en page en mémoire d'une classe CLR est définie par l'implémentation, vous ne pouvez pas la faire correspondre à C++. Ce que vous pouvez faire, c'est que les objets implémentent une interface et fournissent une définition non gérée de cette interface sur une taille non gérée, puis laissez P/Invoke rassembler le tableau. –

Répondre

1

Pouvez-vous lancer un jeton vers un pointeur vide? Assurez-vous que le tableau d'objets est épinglé.

+0

J'ai essayé: VariableObject [] varObj = new VariableObject [numVarObjects]; GCHandle pinnedData = GCHandle.Alloc (varObj, GCHandleType.Pinned); IntPtr ptr = pinnedData.AddrOfPinnedObject(); L'appel Alloc aboutit à: "L'objet contient des données non-primitives ou non-blittables.". – user20493

+0

Vous ne pouvez pas obtenir de pointeur sur un type géré. Un tableau de types gérés est également un type géré et une référence d'objet est un type géré. –

+0

Alors, comment ce tableau peut-il être passé au code non managé? – user20493

1

Ce qui a finalement travaillé:

  1. Passer un tableau de struct, au lieu d'un tableau d'objets (références).
  2. Mettre "[StructLayout (LayoutKind.Sequential, Pack = 1)]" juste avant la définition de structure.
  3. Mettre "[MarshalAs (UnmanagedType.LPWStr)]" avant la chaîne (dans la définition struct) pour que la chaîne apparaisse comme une chaîne de caractères larges du côté C++.
  4. Déclaration d'un tableau de structs pour l'argument dans la déclaration DllImport: "VariableObject [] varObj".
  5. Déclaration d'un pointeur sur la classe en tant que paramètre du côté C++. (La classe C++ reflète la structure C#.): "VariableObject * varObj".
0

Dans votre signature de la méthode C#/Managed, marquer le paramètre d'entrée avec [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 0)] ...

[DllImport(...)] 
public void DoTask 
    (
     ..., 
     [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] results, 
     ... 
    ); 

appeler Ensuite, comme vous l'avez toujours . En outre, dans le code non géré, vous pouvez modifier ce tableau. Je suggère que vous envoyiez un int supplémentaire indiquant au code non managé quelle est la taille du tableau pour empêcher la modification de "tableau hors limite".

Questions connexes