我是不是需要在 C# 中使用来自非托管 C++ dll 的原始数据类型执行 MarshalAs?

Posted

技术标签:

【中文标题】我是不是需要在 C# 中使用来自非托管 C++ dll 的原始数据类型执行 MarshalAs?【英文标题】:Do I need to do MarshalAs with primitive data types from unmanaged C++ dll in C#?我是否需要在 C# 中使用来自非托管 C++ dll 的原始数据类型执行 MarshalAs? 【发布时间】:2018-05-28 04:34:03 【问题描述】:

我有一个基本问题,

我有一个 C++ 非托管 dll,它具有带参数的函数输入和输出一些无符号字符、无符号短、无符号长、有符号字符、有符号短、有符号长数据类型。

我需要对其进行编组还是直接映射它? 如果有的话,最佳做法是什么?

例如 dll

unsigned long SomeFunc(unsigned char variableA);

C#(C# 中的直接映射)

[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.U4)]
public static extern uint SomeFunc(byte variableA);

【问题讨论】:

指定一个已经是默认选择的 UnmanagedType 通常不是问题。但是您确实选择了一个默认值并不总是 U4 的。 long 在 64 位模式下很棘手,它在 Windows 上是 U4,但在 unix 上是 U8。如果此代码必须是可移植的,那么您会倾向于修改 C++ 声明。 感谢您的评论。但我真的不明白你。您能否提供链接或对此进行更多解释,以便我更好地理解。我真的很想知道对此的最佳做法是什么。 【参考方案1】:

大多数数据类型在托管和非托管内存中都有一个共同的表示,并且不需要互操作封送处理程序进行特殊处理。这些类型被称为 blittable 类型,因为它们在托管和非托管代码之间传递时不需要转换。

MSDN:https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types

【讨论】:

如果你链接新版本更好(msdn.microsoft.com/en-us/library/75dwhxf7(v=vs.100).aspx)...旧版本忘记了floatdouble 那么,这行代码够用了吧? [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] public static extern uint SomeFunc(byte variableA); @nutcracker 如果您在 Windows 中工作,并且方法是 cdecl(它没有标记为 stdcall),那么可以。【参考方案2】:

为了扩展mozfox的响应,列表是:bytesbyteshortushortintuintlongulongIntPtrUIntPtrfloatdouble,其中的一维数组([]),其中的struct。缺少bool(可以通过各种方式编组)、char(不要问为什么......我不知道)、string

【讨论】:

以上是关于我是不是需要在 C# 中使用来自非托管 C++ dll 的原始数据类型执行 MarshalAs?的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 和非托管 C++ 之间传递自定义对象

从托管 C# 代码调用非托管 C++ 代码以生成脱机域加入 blob

如何从 C# 导入和使用非托管 C++ 类?

从非托管 c++ 调用 C# 函数(通过托管包装器)

将非托管 c++ 类库暴露给 c#

非托管 C++ 加密字符串转换为 C# byte[]