2009-06-28 5 views
8

J'ai besoin de votre aide avec le scénario suivant:Comment puis-je transmettre des données de MemoryStream à DLL non géré C++ en utilisant P/Invoke

Je lis des données de matériel dans un MemoryStream (C#) et je dois transmettre ces données en mémoire à une DLL implémentée en C++ non géré (en utilisant pointer ??). Les données lues (en 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 est de savoir comment passer le pointeur/référence des données de flux à l'API C++?

Je dois admettre que je suis confus car je suis nouveau en C# - dois-je utiliser dangereux/fixe car les données sont volumineuses ou non pertinentes car l'objet MemoryStream est géré par GC? Un exemple de code/description détaillée serait très utile. Merci

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

BOOL doSomething (void * rawData, int dataLength)

+0

De quel type de données la DLL C++ a-t-elle besoin? – scottm

+0

Il nécessite des données brutes - byte/void *. Je peux changer l'API dll comme requis. –

Répondre

12

Si c'est juste attendre que vous Bytes pouvez lire le MemoryStream dans un tableau d'octets et ensuite passer un pointeur à celui de 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 de la MemoryStream dans un tableau d'octets. Allouer un GCHandle qui:

Une fois attribué, vous pouvez utiliser un GCHandle pour empêcher l'objet géré de collectés par les ordures collecteur lorsqu'un client non géré détient la seule référence. Sans un tel un handle, l'objet peut être collecté par le garbage collector avant que termine son travail 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(); 
} 
+0

Merci. Oui, cette méthode est essentiellement destinée à la compression, de sorte qu'elle nécessite/fonctionne sur les données brutes qui lui sont transmises. Des données étiquetées non sécurisées et curieuses sont placées sur le tas ou la pile en C#? –

+0

C'est la même chose que pour le code non marqué dangereux. – scottm

+0

Juste pour clarifier, ce code n'est pas considéré comme dangereux. – scottm

Questions connexes