0

我尝试调用代码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 代码将使用其内容作为函数指针。我看不出计算大小会如何失败,有人可以帮忙吗?

4

1 回答 1

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() 显式添加引用

射脚的方法很多,祝你好运:)

于 2013-10-16T16:21:13.947 回答