为什么此 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 显然不存在此限制。
我已将其归结为一个简单的示例。我正在编写 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 显然不存在此限制。