2010-04-15 2 views
19

Ich schreibe ein Programm in C#, die eine C++ - Bibliothek verwendet, und aus irgendeinem Grund muss ich einen nicht verwalteten Puffer zuweisen, um es an die lib übergeben. Gibt es eine Möglichkeit, dies in C# zu tun? Grundsätzlich würde ich nur eine malloc in C# tun müssen ...Zuordnung "unmanaged" Speicher in C#

Dank

+0

Was ist mit 'neues Byte [1024]'? –

+2

@John Saunders: Ich weiß nicht, ob das zuverlässig wäre, da der verwaltete Speicher nicht garantiert zusammenhängend ist. Sie möchten es wahrscheinlich auch fixieren, um zu verhindern, dass der GC es während der Verwendung bewegt. – Joshua

+4

@Joshua Huh? Der verwaltete Speicher ist sehr garantiert zusammenhängend. Es ist nicht garantiert, am selben Ort zu bleiben, aber wenn es so ist, ist es zusammenhängend, und es gibt "feste", um es stabil zu halten. –

Antwort

35

so etwas wie dieses Versuchen:

using System; 
using System.Runtime.InteropServices; 

class Example 
{ 
    static void Main() 
    { 
     IntPtr pointer = Marshal.AllocHGlobal(1024); 
    } 
} 

Dies verwendet die Marshal.AllocHGlobal Methode:

Speicher zuordnet aus dem nicht verwalteten Speicher des Prozesses mit der angegebenen Anzahl von Bytes.

+19

Stellen Sie sicher, dass Sie es mit 'FreeHGlobal()' freigeben. Ausnahmesicher möchten Sie wahrscheinlich auch eine 'IDisposable'-Wrapper-Klasse erstellen, um den Speicher zuzuweisen, so dass Sie in einer' using'-Anweisung reservieren können, um den Speicher auf 'Dispose' freizugeben. –

7

Sie können dafür auch ein Byte-Array verwenden.

Sie tun dies durch eine unsichere Routine und die feste Aussage:

static unsafe void PerformOperation() 
{ 
    byte[] buf = new byte[1024]; 
    fixed (void* ptr = &buf[0]) 
    { 
     SomeUnmanagedFunction(new IntPtr(ptr)); 
    } 
} 

Das Problem - und das ist ein sehr wichtiger - ist, dass SomeUnmanagedFunction nicht erlaubt ist, diesen Zeiger zu berühren, nachdem er zurückgekehrt ist und Code hat den festen Block verlassen. Also wenn du so etwas machst:

static void PerformFabulousTrick() 
{ 
    byte[] buf = new byte[1024]; 
    fixed (void *ptr = &buf[0]) 
    { 
     SetBuffer(ptr, buf.Length); 
    } 
    FillBuffer(); // puts data in buf - NOT - may crash hard 
} 

du fragst nur nach Ärger. In diesem Fall möchten Sie wahrscheinlich einen GCHandle verwenden, der ein verwaltetes Objekt im Heap anheften kann. Dies kann auch problematisch sein, da Sie es rechtzeitig lösen müssen oder Sie riskieren, Ihren Heap zu fragmentieren.

Im Allgemeinen würde ich empfehlen, sicherzustellen, dass Sie P/Invoking richtig in der Funktion sind, so dass der vielleicht Marshaller diese Arbeit für Sie erledigen kann. Ich mag eine bessere Lösung als GlobalAlloc, da der Umfang klar ist. Ich kann nicht entscheiden, was ich am wenigsten von GlobalAlloc und GCHandle mag. Beide erfordern Sie mehr Arbeit zu tun, da der GC oder Sprache wird es nicht für Sie tun.

2

So müssen wir nicht verwalteten Speicher zuordnen und freigeben, indem Sie eine bestimmte Anzahl von Bytes verwenden.

// Demonstrate how to call GlobalAlloc and 
// GlobalFree using the Marshal class. 
IntPtr hglobal = Marshal.AllocHGlobal(100); 
Marshal.FreeHGlobal(hglobal)