为什么这种封送处理在Mono中工作,但在MS中失败?

本文关键字:工作 但在 MS 失败 Mono 处理 为什么 | 更新日期: 2023-09-27 18:02:16

我已经将其归结为一个简单的例子。我正在编写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();
但是,这会抛出一个异常:

类型为"System.Runtime.InteropServices"的未处理异常。MarshalDirectiveException'发生在ForestDB.Test.exe

附加信息:方法的类型签名不兼容PInvoke。

注意:我已经尝试了各种MarshalAs组合没有运气。还请注意,我只负责c#方面的事情,C API是由其他人开发的,我无法控制它。

如果这个简单签名不兼容p/Invoke,那到底是什么?为什么它能在Mono的OS X上工作?

为什么这种封送处理在Mono中工作,但在MS中失败?

你知道什么?事实证明,MarshalAs实际上是问题所在,使该属性在Windows上几乎毫无用处。托管端的结构体的所有成员都需要是可篡改类型。这个限制在Mono上显然不存在

相关文章: