【问题标题】:Marshaling an array inside a Struct with methods using C# P/Invoke使用 C# P/Invoke 方法在 Struct 内编组数组
【发布时间】:2012-06-01 03:11:19
【问题描述】:

我用 C 写了一个这样的结构

struct IMAGE {
    unsigned int    x, y;
    unsigned char   **data;
};

谁能告诉我如何编组这个结构以在 C# 中使用?

我的解决方案不起作用。

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class IMAGE
{
            public UInt32 x;
            public UInt32 y;

            public byte[][] data;
};

【问题讨论】:

  • 为什么不在 c# 中简单地创建结构?
  • 因为我的工作是包装一个 C 库以供 C# 调用。
  • here 是一篇好帖子。

标签: c# c++ c pinvoke marshalling


【解决方案1】:

托管数组不同于指针。托管数组需要数组的大小,如果您尝试编组结构,则需要固定大小才能直接编组。

您可以使用MarshalAs attributeSizeConst 参数来设置封送数据时的大小。

但我猜xy 是图像的尺寸,data 的大小取决于这些变量。这里最好的解决方案是将其编组为 IntPtr 并在需要时访问数据:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class IMAGE
{
    public UInt32 x;
    public UInt32 y;

    private IntPtr data;

    public byte[][] Data
    {
        get
        {
            byte[][] newData = new byte[y][];

            for(int i = 0; i < y; i++)
            {
                newData[i] = new byte[x];
                Marshal.Copy(new IntPtr(data.ToInt64() + (i * x)), newData[i], 0, x);
            }

            return newData;
        }

        set
        {
            for (int i = 0; i < value.Length; i++)
            {
                Marshal.Copy(value[i], 0, new IntPtr(data.ToInt64() + (i * x)), value[i].Length);
            }
        }
    }
}

如果您被允许使用不安全的代码,您可以将IntPtr 更改为byte** 并直接使用它。

使用 setter,您可能希望在盲目写入非托管内存之前验证值的维度。

【讨论】:

    【解决方案2】:

    我的猜测是:

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class IMAGE
    {
                public UInt32 x;
                public UInt32 y;
    
                public ref IntPtr data;
    };
    

    一个非常方便的参考是 p/invoke cheatsheet

    【讨论】:

    • ref 用于方法参数,而不是类成员。您的回答会产生编译器错误:Invalid token 'ref' in class, struct, or interface member defintion.
    猜你喜欢
    • 2012-01-21
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多