P/Invoke from C to C# without knowing size of arra

2019-05-22 18:29发布

Right know in my code I have structure declared as like this, with fixed this 16, know at compile time.

struct CONSOLE_SCREEN_BUFFER_INFOEX
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public int ColorTable[];
}

but what I need is to be able to have this structure:

struct CONSOLE_SCREEN_BUFFER_INFOEX
{
   int arraySize;
   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
   public int ColorTable[];
}

get the arraySize from C function response, initialize ColorTable array with proper size, put result of response into ColorTable.

Not sure if it's possible, just doing investigation right now, and any comments are very welcome.

1条回答
我命由我不由天
2楼-- · 2019-05-22 18:57

You can do this easily enough with some manual marshalling using the Marshal class. For example:

[DllImport(@"MyLib.dll")]
private static extern void Foo(IntPtr structPtr);

private static IntPtr StructPtrFromColorTable(int[] colorTable)
{
    int size = sizeof(int) + colorTable.Length*sizeof(int);
    IntPtr structPtr = Marshal.AllocHGlobal(size);
    Marshal.WriteInt32(structPtr, colorTable.Length);
    Marshal.Copy(colorTable, 0, structPtr + sizeof(int), colorTable.Length);
    return structPtr;
}

private static int[] ColorTableFromStructPtr(IntPtr structPtr)
{
    int len = Marshal.ReadInt32(structPtr);
    int[] result = new int[len];
    Marshal.Copy(structPtr + sizeof(int), result, 0, len);
    return result;
}

static void Main(string[] args)
{
    int[] colorTable = new int[] { 1, 2, 3 };
    IntPtr structPtr = StructPtrFromColorTable(colorTable);
    try
    {
        Foo(structPtr);
        colorTable = ColorTableFromStructPtr(structPtr);
    }
    finally
    {
        Marshal.FreeHGlobal(structPtr);
    }
}
查看更多
登录 后发表回答