Wie kann ich passieren Memory Daten auf nicht verwalteten C ++ DLL unter Verwendung von P / Invoke
-
20-08-2019 - |
Frage
Ich brauche Ihre Hilfe mit dem folgende Szenario:
Ich lese einige Daten von der Hardware in einen Memorystream (C #) und ich brauche diese Daten im Speicher in einer DLL in nicht verwalteten C implementiert passieren ++ (mit Zeigern ??). Die gelesenen Daten (in Strom) sehr groß (Megabyte). Ich verstehe, dass ich P / diese dll aufrufen, aber was ich bin nicht sicher, wie der Zeiger / Referenz der Stream-Daten an die C ++ API zu übergeben?
Ich muss zugeben, ich bin verwirrt, wie ich C # bin hier - muss ich da die Daten unsicher / Fest verwenden groß ist oder diese sind irrelevant, da Objekt Memory von GC verwaltet wird? Einige Beispiel-Code / ausführliche Beschreibung wäre sehr hilfreich. Dank
Signatur von nicht verwalteten API:
BOOL doSomething (void * rawData, int dataLength)
Lösung
Wenn es nur Bytes erwartet Sie das Memorystream in eine Byte-Array lesen und dann einen Zeiger auf das an die Methode übergeben.
Sie müssen die externe Methode deklarieren:
[DllImport("mylibrary.dll", CharSet = CharSet.Auto)]
public static extern bool doSomething(IntPtr rawData, int dataLength);
Dann lesen Sie den Bytes aus dem Memorystream in einen Byte-Array. Vergeben Sie einen GCHandle welche:
Sobald zugewiesen, können Sie eine GCHandle verwenden das verwaltete Objekt zu verhindern, durch den Müll gesammelt Sammler, wenn ein nicht verwalteten Client hält die einzige Referenz. ohne eine solche ein Griff, kann das Objekt gesammelt werden vom Garbage Collector vor Abschluss seiner Arbeit im Namen der nicht verwalteten Client.
Und schließlich verwenden die AddrOfPinnedObject Methode ein IntPtr zu bekommen, um 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();
}