Comment puis-je transmettre des données MemoryStream à une DLL C ++ non gérée à l'aide de P / Invoke

StackOverflow https://stackoverflow.com/questions/1054009

Question

J'ai besoin de votre aide pour le scénario suivant:

Je lis des données matérielles dans un MemoryStream (C #) et j’ai besoin de les transmettre en mémoire à une dll implémentée en C ++ non géré (à l’aide du pointeur ??). Les données lues (dans le flux) sont très volumineuses (mégaoctets). Je comprends que je peux P / Invoke cette dll mais ce que je ne suis pas sûr, c'est comment passer le pointeur / référence des données du flux à l'API C ++?

Je dois admettre que je suis confus, car je suis novice en C #. Dois-je utiliser unsafe / fixed du fait que les données sont volumineuses ou qu'elles ne sont pas pertinentes étant donné que l'objet MemoryStream est géré par le GC? Quelques exemples de code / description détaillée seraient très utiles. Merci

Signature de l'API non gérée:

BOOL doQuelque chose (void * rawData, int dataLength)

Était-ce utile?

La solution

Si vous n'attendez que des octets, vous pouvez lire le MemoryStream dans un tableau d'octets, puis lui transmettre un pointeur sur la méthode.

Vous devez déclarer la méthode externe:

[DllImport("mylibrary.dll", CharSet = CharSet.Auto)]
public static extern bool doSomething(IntPtr rawData, int dataLength);

Ensuite, lisez les octets du MemoryStream dans un tableau d'octets. Allouer un GCHandle qui:

  

Une fois alloué, vous pouvez utiliser une GCHandle   pour empêcher l'objet géré de   être ramassé à la poubelle   collecteur lorsqu'un client non géré   détient la seule référence. Sans une telle   une poignée, l'objet peut être collecté   par le ramasse-miettes avant   achève ses travaux au nom du   client non géré.

Enfin, utilisez la méthode AddrOfPinnedObject pour obtenir un IntPtr à transmettre à la dll C ++.

private void CallTheMethod(MemoryStream memStream)
{
   byte[] rawData = new byte[memStream.Length];
   memStream.Read(rawData, 0, memStream.Length);

   GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
   IntPtr address = handle.AddrOfPinnedObject ();

   doSomething(address, rawData.Length);
   rawDataHandle.Free();
 }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top