我尝试调用代码int size = Marshal.SizeOf(typeof(MyStruct))
,但它抛出以下异常:
类型'MyStruct'不能作为非托管结构封送;没有有意义的大小或偏移量可以计算出来。
我的结构如下:
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
[MarshalAs(UnmanagedType.U4)]
public UInt32 version;
[MarshalAs(UnmanagedType.FunctionPtr)]
public IntPtr Start;
[MarshalAs(UnmanagedType.FunctionPtr)]
public IntPtr Stop;
// And a bunch more IntPtr, all declared the same way.
}
结构应该传递给C-land,C代码将把它的内容用作函数指针。我无法看到计算大小会失败,任何人都可以帮忙吗?
答案 0 :(得分:3)
UnmanagedType.FunctionPtr要求该字段为委托类型。在封送结构之后,它将是C端的函数指针。使用[MarshalAs]是多余的,代表已经被这样封送了。所以,粗略地说:
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
[MarshalAs(UnmanagedType.U4)]
public UInt32 version;
public Action Start;
public Func<bool> Stop;
// etc..
}
更改委托类型以匹配相应C函数指针的函数签名。您经常需要声明自己的委托类型,以便为其提供[UnmanagedFunctionPointer]属性以匹配C函数的调用约定。通常是CallingConvention.Cdecl,而不是默认的Stdcall。
初始化这样的结构时必须非常小心。您创建并分配给字段的委托对象必须在别处引用,以防止它们被垃圾收集。通过将它们存储在C代码可以进行调用的类对象中,通过将它们存储在静态变量中或通过使用GCHandle.Alloc()显式添加引用来保存它们。
有很多方法可以拍脚,祝你好运:)