2009-06-28 2 views
8

ich Ihre Hilfe mit dem folgenden Szenario müssen:Wie kann ich Memory Daten auf nicht verwalteten C++ DLL übergeben mit P/Invoke

ich einige Daten aus Hardware in einen Memorystream (C#) lese und ich brauche diese Daten zu übergeben im Speicher zu einer DLL in nicht verwaltetem C++ implementiert (mit Zeiger ??). Die Daten lesen (in Stream) ist sehr groß (Megabyte). Ich verstehe, dass ich P/Invoke diese DLL kann, aber was ich nicht sicher bin, ist, wie man den Zeiger/den Bezug der Stromdaten zur C++ API gibt?

Ich muss zugeben, ich bin verwirrt, da ich C# neu bin - muss ich unsichere/behoben verwenden, da Daten groß sind oder diese irrelevant sind, da MemoryStream-Objekt von GC verwaltet wird? Ein Beispielcode/eine detaillierte Beschreibung wäre sehr hilfreich. Dank

Signatur von nicht verwalteten API:

BOOL doSomething (void * rawData, int dataLength)

+0

Welchen Datentyp benötigt die C++ - DLL? – scottm

+0

Es erfordert rohe Daten - Byte/void *. Ich kann die DLL API wie erforderlich ändern. –

Antwort

12

Wenn es nur Bytes erwartet Sie das Memorystream in ein Byte-Array lesen und dann einen Zeiger auf das passieren zu die Methode.

Sie haben die externe Methode deklarieren:

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

Dann werden die Bytes aus dem Memorystream in ein Byte-Array lesen. Weisen Sie eine GCHandle die:

Einmal zugewiesen, können Sie eine GCHandle verwenden können das verwaltete Objekt von zu verhindern, indem sie den Müll Sammler gesammelt wird, wenn ein nicht verwalteten Client die einzige Referenz hält. Ohne diese ein Griff, kann das Objekt durch den Garbage Collector vor Abschluss seiner Arbeit im Namen der nicht verwalteten Client gesammelt werden.

Und schließlich, verwenden Sie die AddrOfPinnedObject-Methode, um ein IntPtr an die C++ - DLL zu übergeben.

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

Danke. Ja, diese Methode ist im Grunde für die Komprimierung gedacht, so dass sie an Rohdaten, die an sie übergeben werden, arbeiten wird. Auch nur neugierig unsichere markierte Daten wird auf Heap oder Stapel in C# platziert? –

+0

Es ist das gleiche wie für Code nicht als unsicher markiert. – scottm

+0

Nur zur Klarstellung, dieser Code gilt nicht als unsicher. – scottm

Verwandte Themen