C# 中的 C++ int & long 编组

Posted

技术标签:

【中文标题】C# 中的 C++ int & long 编组【英文标题】:C++ int & long marshalling in C# 【发布时间】:2010-12-27 20:02:16 【问题描述】:

我目前正在将专有 dll(一种 API)移植到 C#,在编组一些使用的数据类型时遇到了一些问题。

例如API头文件定义了以下类型:

typedef unsigned int  tINT;  /* natural unsigned */
typedef signed int    tINTs; /* natural signed */
typedef unsigned int  tLONG; /* 32 bit unsigned */
typedef unsigned long tPTR;  /* 32/64-bit pointer */

然后我例如有以下函数定义:

tINTs SomeApiFunction ( const tPTR hdl, tINT param );

我通常将int 直接与C# 的int (Int32) 或未签名版本进行编组。 API 的tLONGtINT 是一样的(至少对于API)。但我不确定tPTR。我现在在 C# 中将其设为 uint,因为它是 32 位 int,但我不确定 long 在 64 位机器上的表现如何。

我必须做些什么来确保 API 可以在 32 位和 64 位机器上正常工作?

这就是我现在要做的:

[DllImport( "api.dll" )]
public static extern int SomeApiFunction ( uint hdl, uint param );

遗憾的是,API 并没有很好的记录,因此我不确定所有这些(重叠的)typedef 的意图是什么。除了我上面包含的标题 cmets 之外,没有关于实际类型的信息。

【问题讨论】:

【参考方案1】:

尝试将其编组为IntPtr。 IntPtr 在 .Net 中在 32 位系统上为 4 个字节,在 64 位系统上为 8 个字节。

【讨论】:

哦,只是一个快速的附加问题:我应该使用IntPtr 还是UIntPtr,因为那里的指针是 unsigned 长的? 除非你因为指针算法而在处理负值时遇到问题,否则你仍然应该使用 IntPtr。来自 msdn 文档: IntPtr 类型符合 CLS,而 UIntPtr 类型不符合。在公共语言运行库中仅使用 IntPtr 类型。提供 UIntPtr 类型主要是为了与 IntPtr 类型保持架构对称性。【参考方案2】:

它是 C/C++ 编译器的实现细节。您应该通过注释并声明它为 IntPtr。如果代码是由 MSVC 编译器编译的,那么它将无法在 64 位模式下工作,它会长期使用 32 位。不足以存储指针。

【讨论】:

你的意思是什么,它不能在 64 位上工作?我的示例 C# 代码,或整个 API(不会让我感到惊讶。)? 整个 API 以及您的 C# 示例。您是否有该 DLL 的预构建 64 位版本?您通常可以四处逛逛并了解它是如何构建的。 不,我只有一个 DLL.. :/ 好吧,那就别担心了。您必须将 C# 项目的目标平台设置为 x86。使用 IntPtr,也许他们有一天会修复它。 啊,好的,我稍后会尝试联系供应商;现在它只适用于 x86 就足够了。非常感谢:)【参考方案3】:

这里是good list of type correspondence.

对于指针类型,在 C# 中通常为 IntPtr

【讨论】:

【参考方案4】:

如果我没记错的话 int uint 和其他原始类型是底层 Windows API 的正确类型。

但是,对于指针,最好在 C# 端使用 IntPtr,在 C/C++ 端使用 void*

【讨论】:

以上是关于C# 中的 C++ int & long 编组的主要内容,如果未能解决你的问题,请参考以下文章

C++ 中的“long”、“long long”、“long int”和“long long int”有啥区别?

64位机器中的C++ int vs long long

在C#中long与int64有啥区别吗

在C#中long与int64有啥区别吗

C++ 中的 <map> 的 C# 等价物是啥? [复制]

C#中long和int的区别?