使用 C# P/Invoke 方法在 Struct 内编组数组
Posted
技术标签:
【中文标题】使用 C# P/Invoke 方法在 Struct 内编组数组【英文标题】:Marshaling an array inside a Struct with methods using C# P/Invoke 【发布时间】: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 是一篇好帖子。 【参考方案1】:托管数组不同于指针。托管数组需要数组的大小,如果您尝试编组结构,则需要固定大小才能直接编组。
您可以使用MarshalAs
attribute 的SizeConst
参数来设置封送数据时的大小。
但我猜x
和y
是图像的尺寸,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.
以上是关于使用 C# P/Invoke 方法在 Struct 内编组数组的主要内容,如果未能解决你的问题,请参考以下文章