正确的方式编组SIZE_T *?(Correct way to marshal SIZE_T*?)

2019-07-02 17:45发布

我有以下的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,但我一直无法拿出任何其他可行的解决方案。

Answer 1:

使用IntPtr和/或UIntPtr 适当做-的类型有专门用于此目的! 我不明白为什么你认为这是一个“丑陋的黑客”。 我也不能确定你提出的替代方案是什么-任何一种属性的允许值映射到uint会本身错误的,因为C# uint是保证无论架构的32位,等等64位平台,要正确封送它,那就要修剪它的一半,丢失数据,并有可能使结果没用。



Answer 2:

UIntPtr是正确的类型使用。

为size_t是无符号,指针大小的整数,这正是UIntPtr手段。 该“PTR”的名字可以是一个有点混乱,我同意。 它不会实际上意味着“这是一个指针”,它的意思是“这是一个指针大小的整数”。 所以,你的声明将是:

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


文章来源: Correct way to marshal SIZE_T*?