18

私はこのような構造体を持っています

struct MyStruct
{
    public int field1;
    public int field2;
    public int field3;
}

この構造体の配列へのポインタがあります。したがって、このポインターから配列を取得する必要があります。Marshal.PtrToStructure を使用しようとしましたが、メモリ読み取りエラーが発生しました。これは私の方法です:

public MyStruct[] GetArrayOfStruct(IntPtr pointerToStruct, int length)
{
    var sizeInBytes = Marshal.SizeOf(typeof(TCnt));
    MyStruct[] output = new MyStruct[length];

    for (int i = 0; i < length; i++)
    {
        IntPtr p = new IntPtr((pointerToStruct.ToInt32() + i * sizeInBytes));

        output[i] = (MyStruct)System.Runtime.InteropServices.Marshal.PtrToStructure(p, typeof(MyStruct));
    }

    return output;
}

それで、私は何を間違っていますか?

4

3 に答える 3

11

構造体のサイズが固定されていると仮定すると、この関数は私にとってはうまくいきました:

public static void MarshalUnmananagedArray2Struct<T>(IntPtr unmanagedArray, int length, out T[] mangagedArray)
{
    var size = Marshal.SizeOf(typeof(T));
    mangagedArray = new T[length];

    for (int i = 0; i < length; i++)
    {
        IntPtr ins = new IntPtr(unmanagedArray.ToInt64() + i * size);
        mangagedArray[i] = Marshal.PtrToStructure<T>(ins);
    }
 }
于 2016-11-02T09:23:25.723 に答える
4

2 つの問題。Marshal.SizeOf() 呼び出しで MyStruct の代わりに TCnt を使用します。IntPtr 演算は 64 ビット マシンでは機能しません。IntPtr.ToInt64() を使用するか、(long) にキャストする必要があります。

もちろん、間違った IntPtr または長さを取得する可能性もあります。デバッグ + Windows + メモリ + メモリ 1 を使用し、基本的な検証のために [アドレス] ボックスに "pointerToStruct" を入力します。

于 2011-07-19T12:53:21.593 に答える
2

CとC#の構造体は同じものではありません。違いの1つは、C#では、構造体を順番に配置することを明示的に要求する必要があることです。[StructLayout(LayoutKind.Sequential)]あなたがあなたの構造を書いたり[StructLayout(LayoutKind.Explicit)]属性を付けたりしなかったなら 、私はあなたがこのようにそれを管理できるとは思わない。PtrToStructureMicrosoftは、構造を非管理メモリから管理メモリに変換するために使用されると述べています

この属性を構造体に追加することが役立つかどうかをテストする必要があります。それでもメモリの割り当てに役立たない場合は、構造体の初期化にMarshal.AllocHGlobal(IntPtr)使用してから、を使用してみてください。これが機能する場合は、管理対象メモリでは使用できませんMarshal.CopyPtrToStructurePtrToStructure

于 2011-07-19T14:00:48.243 に答える