soo*_*iln 17 c# c++ pinvoke marshalling intptr
我有以下C++函数定义,我试图通过托管代码通过PInvoke调用:
bool FooBar(SIZE_T* arg1);
Run Code Online (Sandbox Code Playgroud)
我的管理声明如下:
[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern bool FooBar(ref uint arg1);
Run Code Online (Sandbox Code Playgroud)
有些人可能会注意到我最终做的同样的错误.这不是64位便携式.SIZE_T的大小可变(32-64位),指针也是如此.在托管大小上,指针正确转换为64位,但uint没有,并且您最终可以在arg1的高位中使用垃圾.这是一个特别持久的错误,因为垃圾通常只是零:(
我已经开始工作的唯一解决方案是以下管理声明:
[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern bool FooBar(ref IntPtr arg1);
Run Code Online (Sandbox Code Playgroud)
这当然有效,因为IntPtr可以正确地改变它的大小.在我的代码中,我只是将IntPtr视为一个整数,它可以工作,虽然它看起来像一个丑陋的黑客.在我看来应该有一些方法来正确指定,也许使用UnmanagedType.SysUInt,但我无法提出任何其他工作解决方案.
Pav*_*aev 20
使用IntPtr和/或UIntPtr 正在正确地执行 - 这些类型专门用于此目的!我不明白为什么你认为这是一个"丑陋的黑客".我也不确定你提议的替代方案是什么 - 允许映射到的任何类型的属性uint本质上都是错误的,因为uint无论架构如何,C#都保证是32位,所以在64位平台上,要正确编组它,它必须修剪一半,丢失数据,并可能使结果无用.
EMP*_*EMP 14
UIntPtr是要使用的正确类型.
size_t是一个无符号的,指针大小的整数,这正是UIntPtr的含义.我同意,名字中的"ptr"可能有点令人困惑.它实际上并不意味着"这是一个指针",它意味着"这是一个指针大小的整数".所以你的声明是:
[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern bool FooBar(ref UIntPtr arg1);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9754 次 |
| 最近记录: |