为什么此 Marshaling 在 Mono 中工作但在 MS 上失败?

Why does this Marshaling work in Mono but fail on MS?

我已将其归结为一个简单的示例。我正在编写 C# 和 C 之间的一些互操作代码,并且在非托管方面有以下非常简单的结构:

typedef struct {
    bool create_if_missing;
    fdb_custom_cmp_variable custom_cmp;
} fdb_kvs_config;

typedef int (*fdb_custom_cmp_variable)(void *a, size_t len_a,
                                   void *b, size_t len_b);

所以我在托管端创建了这个:

public struct fdb_kvs_config
{
    [MarshalAs(UnmanagedType.I1)]
    public bool create_if_missing;

    [MarshalAs(UnmanagedType.FunctionPtr)]
    public IntPtr custom_cmp;
}

我想使用这个非托管函数

extern __declspec(dllexport)
fdb_kvs_config fdb_get_default_kvs_config(void);

所以我有这个等价物:

[DllImport("forestdb", CallingConvention=CallingConvention.Cdecl)]
public static extern fdb_kvs_config fdb_get_default_kvs_config();

但是,这会引发异常:

An unhandled exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in ForestDB.Test.exe

Additional information: Method's type signature is not PInvoke compatible.

注意:我尝试了各种 MarshalAs 组合,但都没有成功。另请注意,我只负责 C# 方面的事情,C API 是由其他人开发的,我无法控制它。

如果这个简单的签名不 P/Invoke 兼容那到底是什么?对于奖励积分,为什么它在 OS X in Mono 上有效?

嗯,你知道什么。事实证明 MarshalAs 实际上是问题所在,使得该属性在 Windows 上几乎毫无用处。托管端结构的所有成员都需要 blittable types。 Mono 显然不存在此限制。