我将其归结为一个简单的示例。我正在 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 的 Mono 上运行?
最佳答案
那么你知道什么。事实证明,MarshalAs 实际上是问题所在,使得该属性在 Windows 上几乎毫无用处。托管端结构体的所有成员都需要是 blittable types 。 Mono 显然不存在这个限制。
关于c# - 为什么此编码在 Mono 中有效但在 MS 中失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31354476/