正确的方法来组织SIZE_T *?

我有以下C ++函数定义,我试图通过托管代码通过PInvoke调用:

bool FooBar(SIZE_T* arg1); 

我的管理声明如下:

 [DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)] private static extern bool FooBar(ref uint arg1); 

有些人可能会注意到我最终做的同样的错误。 这不是64位便携式。 SIZE_T的大小可变(32-64位),指针也是如此。 在托管大小上,指针正确转换为64位,但uint没有,并且您最终可以在arg1的高位中使用垃圾。 这是一个特别持久的错误,因为垃圾通常只是零:(

我已经开始工作的唯一解决方案是以下管理声明:

 [DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)] private static extern bool FooBar(ref IntPtr arg1); 

这当然有效,因为IntPtr可以正确地改变它的大小。 在我的代码中,我只是将IntPtr视为一个整数,它可以工作,虽然它看起来像一个丑陋的黑客。 在我看来,应该有一些方法来正确指定,也许使用UnmanagedType.SysUInt,但我一直无法提出任何其他工作解决方案。

使用IntPtr和/或UIntPtr正确地执行它 – 这些类型专门用于此目的! 我不明白为什么你认为这是一个“丑陋的黑客”。 我也不确定你提议的替代方案是什么 – 任何允许将值映射到uint的属性本质上都是错误的,因为无论架构如何,C# uint都保证是32位的,所以64-位平台,要正确编组它,它必须修剪一半,丢失数据,并可能使结果无用。

UIntPtr是要使用的正确类型。

size_t是一个无符号的,指针大小的整数,这正是UIntPtr的意思。 我同意,名字中的“ptr”可能有点令人困惑。 它实际上并不意味着“这是一个指针”,它意味着“这是一个指针大小的整数”。 所以你的声明是:

 [DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)] private static extern bool FooBar(ref UIntPtr arg1);