P/在不知道数组大小的情况下从C调用到C#

P/在不知道数组大小的情况下从C调用到C#,c#,arrays,pinvoke,unsafe,C#,Arrays,Pinvoke,Unsafe,在我的代码中,我的结构声明如下,修复了16,编译时知道 struct CONSOLE_SCREEN_BUFFER_INFOEX { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public int ColorTable[]; } 但我需要的是能够有这样的结构: struct CONSOLE_SCREEN_BUFFER_INFOEX { int arraySize; [MarshalAs(UnmanagedType.By

在我的代码中,我的结构声明如下,修复了16,编译时知道

struct CONSOLE_SCREEN_BUFFER_INFOEX
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public int ColorTable[];
}
但我需要的是能够有这样的结构:

struct CONSOLE_SCREEN_BUFFER_INFOEX
{
   int arraySize;
   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
   public int ColorTable[];
}
从C函数响应中获取arraySize,初始化大小合适的ColorTable数组,将响应结果放入ColorTable


不确定是否可能,只是现在正在进行调查,欢迎任何评论

使用
封送
类进行一些手动封送,就可以很容易地做到这一点。例如:

[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);
    }
}

声明该字段不是正确的方法,应该使用[Marshallas(UnmanagedType.ByValArray,SizeConst=16)]public int[]ColorTable来完成。这会给你更多的绳子,但不足以让它取决于大小字段。你需要编写一个自定义封送拆收器。嘿,汉斯,你是对的,这正是我现在所做的:[Marshallas(UnmanagedType.ByValArray,SizeConst=16)],我只是将其与Jon的代码相似以避免混淆。但现在的请求是将其设置为[Marshallas(UnmanagedType.ByValArray,SizeConst=0)],然后更改大小,当大小已知时,定制封送器正是我感兴趣的,我只是以前从未接触过它,所以需要知道从何处开始使用定制示例会更好。所有这些额外的字段对于讨论来说都是多余的。Hans说得对,这里不需要
不安全的
。乔恩大概只是把这当作一种说明
修复的方法。但是
ByValArray
是正确的方法。您可以使用自定义封送拆收器。或者你可以使用
IntPtr
Marshal.AllocHGlobal
Marshal.PtrToStructure
Marshal.Copy
。你最大的错误是把你的问题建立在一个非常糟糕的例子上。询问合适的问题,显示您真正需要与之交互的内容。请编辑,我的问题,以便与我的真实情况更加相关。@Stanislav您可能对这个问题感兴趣: