web-dev-qa-db-ja.com

「アンマネージ」メモリをc#に割り当てる

私はC++ライブラリを使用するプログラムをc#で作成しています。何らかの理由で、アンマネージバッファーを割り当ててlibに渡す必要があります。これをC#で行う方法はありますか?基本的には、C#でmallocを実行するだけです...

ありがとう

23
Blitzz

このようなものを試してください:

using System;
using System.Runtime.InteropServices;

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

これは Marshal.AllocHGlobal メソッド:

指定されたバイト数を使用して、プロセスのアンマネージメモリからメモリを割り当てます。

44
Andrew Hare

これにはバイト配列を使用することもできます。

これを行うには、安全でないルーチンと固定ステートメントを使用します。

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

問題-これは重要な問題です-は、SomeUnmanagedFunctionが返され、コードが固定ブロックを終了した後、そのポインターに触れることができないことです。したがって、次のようなことをすると:

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
}

あなたはトラブルだけを求めています。この場合、おそらく管理オブジェクトをヒープに固定できる GCHandle を使用する必要があります。これは、タイムリーにピンを固定解除する必要がある、またはヒープを断片化するリスクがあるという点でも問題になる可能性があります。

一般に、おそらくマーシャラーがこの作業を実行できるように、関数に正しくP/Invokingしていることを確認することをお勧めします。スコープが明確なため、GlobalAllocよりも修正が好きです。 GlobalAllocとGCHandleのどちらが一番好きか判断できません。 GCまたは言語はあなたのためにそれをしないので、両方が必要ですより多くの作業を行う必要があります。

9
plinth

これが、特定のバイト数を使用してアンマネージメモリを割り当て、解放する方法です。

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