为什么可以';我对这个C#结构执行Marshal.SizeOf()吗?

为什么可以';我对这个C#结构执行Marshal.SizeOf()吗?,c#,.net,interop,C#,.net,Interop,我尝试调用代码int size=Marshal.SizeOf(typeof(MyStruct)),但它引发以下异常: 类型“MyStruct”不能作为非托管结构封送;无法计算有意义的大小或偏移量 我的结构如下: [StructLayout(LayoutKind.Sequential)] public struct MyStruct { [MarshalAs(UnmanagedType.U4)] public UInt32 version; [MarshalAs(Unman

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

UnmanagedType.FunctionPtr要求字段为委托类型。结构封送后,它将是C端的函数指针。使用[MarshalAs]是多余的,委托已经被这样封送了。因此,大致上:

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
    [MarshalAs(UnmanagedType.U4)]
    public UInt32 version;
    public Action Start;
    public Func<bool> Stop;
    // etc..
}
[StructLayout(LayoutKind.Sequential)]
公共结构MyStruct
{
[Marshallas(UnmanagedType.U4)]
公共UInt32版本;
公共行动开始;
公共职能站;
//等等。。
}
更改委托类型以匹配相应C函数指针的函数签名。通常必须声明自己的委托类型,以便为其指定[UnmanagedFunctionPointer]属性,以匹配C函数的调用约定。通常调用convention.Cdecl,而不是Stdcall的默认值

在初始化这样的结构时,必须非常小心。您创建并分配给字段的委托对象必须在别处引用,以防止它们被垃圾回收。或者将它们存储在一个类对象中,该类对象保证在C代码能够调用的时间内一直存在,或者将它们存储在一个静态变量中,或者使用GCHandle.Alloc()显式添加一个引用


有很多方法可以射击你的脚,祝你好运:)

非托管类型。FunctionPtr要求字段为委托类型。结构封送后,它将是C端的函数指针。使用[MarshalAs]是多余的,委托已经被这样封送了。因此,大致上:

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
    [MarshalAs(UnmanagedType.U4)]
    public UInt32 version;
    public Action Start;
    public Func<bool> Stop;
    // etc..
}
[StructLayout(LayoutKind.Sequential)]
公共结构MyStruct
{
[Marshallas(UnmanagedType.U4)]
公共UInt32版本;
公共行动开始;
公共职能站;
//等等。。
}
更改委托类型以匹配相应C函数指针的函数签名。通常必须声明自己的委托类型,以便为其指定[UnmanagedFunctionPointer]属性,以匹配C函数的调用约定。通常调用convention.Cdecl,而不是Stdcall的默认值

在初始化这样的结构时,必须非常小心。您创建并分配给字段的委托对象必须在别处引用,以防止它们被垃圾回收。或者将它们存储在一个类对象中,该类对象保证在C代码能够调用的时间内一直存在,或者将它们存储在一个静态变量中,或者使用GCHandle.Alloc()显式添加一个引用


有很多方法可以射击你的脚,祝你好运:)

非托管类型。FunctionPtr要求字段为委托类型。结构封送后,它将是C端的函数指针。使用[MarshalAs]是多余的,委托已经被这样封送了。因此,大致上:

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
    [MarshalAs(UnmanagedType.U4)]
    public UInt32 version;
    public Action Start;
    public Func<bool> Stop;
    // etc..
}
[StructLayout(LayoutKind.Sequential)]
公共结构MyStruct
{
[Marshallas(UnmanagedType.U4)]
公共UInt32版本;
公共行动开始;
公共职能站;
//等等。。
}
更改委托类型以匹配相应C函数指针的函数签名。通常必须声明自己的委托类型,以便为其指定[UnmanagedFunctionPointer]属性,以匹配C函数的调用约定。通常调用convention.Cdecl,而不是Stdcall的默认值

在初始化这样的结构时,必须非常小心。您创建并分配给字段的委托对象必须在别处引用,以防止它们被垃圾回收。或者将它们存储在一个类对象中,该类对象保证在C代码能够调用的时间内一直存在,或者将它们存储在一个静态变量中,或者使用GCHandle.Alloc()显式添加一个引用


有很多方法可以射击你的脚,祝你好运:)

非托管类型。FunctionPtr要求字段为委托类型。结构封送后,它将是C端的函数指针。使用[MarshalAs]是多余的,委托已经被这样封送了。因此,大致上:

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
    [MarshalAs(UnmanagedType.U4)]
    public UInt32 version;
    public Action Start;
    public Func<bool> Stop;
    // etc..
}
[StructLayout(LayoutKind.Sequential)]
公共结构MyStruct
{
[Marshallas(UnmanagedType.U4)]
公共UInt32版本;
公共行动开始;
公共职能站;
//等等。。
}
更改委托类型以匹配相应C函数指针的函数签名。通常必须声明自己的委托类型,以便为其指定[UnmanagedFunctionPointer]属性,以匹配C函数的调用约定。通常调用convention.Cdecl,而不是Stdcall的默认值

在初始化这样的结构时,必须非常小心。您创建并分配给字段的委托对象必须在别处引用,以防止它们被垃圾回收。或者将它们存储在一个类对象中,该类对象保证在C代码能够调用的时间内一直存在,或者将它们存储在一个静态变量中,或者使用GCHandle.Alloc()显式添加一个引用


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

谢谢你的反馈。我目前正在通过执行
Marshal.GetFunctionPointerForDelegate(无论什么)
填充结构。出于各种原因,我希望将结构成员保留为
IntPtr
-如果我只是删除
[marshallas(UnmanagedType.FunctionPtr)]
这是否兼容?使用GetFunctionPointerForDelegate()不会改变答案中的任何内容,同样的问题也适用。是的,就像将字段声明为deleg一样