Correct way to marshal SIZE_T*?

走远了吗. 提交于 2019-11-29 06:19:42

问题


I have the following C++ function definition, which I am trying to call through PInvoke from managed code:

bool FooBar(SIZE_T* arg1);

My managed declaration looked as follows:

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

Some of you may notice the same bug I eventually did. This is not 64bit portable. SIZE_T is of variable size (32-64 bit) as is the pointer to it. On the managed size the pointer correctly translates to 64bit, but the uint does not, and you can end up with trash in the upper bits of arg1. This was an especially persistent error since the trash was often just zeros :(

The only solution I have gotten to work is the following managed declaration:

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

This works of course because IntPtr can vary its size correctly. In my code I just treat the IntPtr as an integer, and it works, though it looks like an ugly hack. It seems to me there should be some way to specify this properly, perhaps using UnmanagedType.SysUInt, but I have been unable to come up with any other working solution.


回答1:


Using IntPtr and/or UIntPtr is doing it properly - the types are there specifically for this purpose! I do not understand why you consider it an "ugly hack". I'm also not sure what your proposed alternative would be - any kind of attribute to allow values to be mapped to uint would be inherently wrong, because C# uint is guaranteed to be 32-bit regardless of the architecture, and so on 64-bit platform, to marshal it correctly, it would have to trim half of it, losing data, and likely rendering the result useless.




回答2:


UIntPtr is the correct type to use.

size_t is an unsigned, pointer-sized integer and that's exactly what UIntPtr means. The "ptr" in the name can be a bit confusing, I agree. It doesn't actually mean "this is a pointer", it means "this is a pointer-sized integer". So your declaration would be:

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


来源:https://stackoverflow.com/questions/1309509/correct-way-to-marshal-size-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!