我是C#的新手,所以我查看了this问题,但我仍然不确定在编组第二个问题时是否应该包含 ref 关键字使用p / invoke的GetWindoInfo()Win32 API调用的参数:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", EntryPoint = "GetWindowInfo", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetWindowInfo(IntPtr hwnd, [MarshalAs(UnmanagedType.Struct)] ref tagWINDOWINFO pwi);
从MSDN documentation获取参考:
ref关键字导致参数通过引用传递,而不是通过引用传递 值。
所以在这种情况下我的代码似乎是正确的,对吧?是否会更改编组子句而不是封送UnmanagedType.LPStruct并删除 ref 关键字导致同样的事情?像这样:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", EntryPoint = "GetWindowInfo", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetWindowInfo(IntPtr hwnd, [MarshalAs(UnmanagedType.LPStruct)] tagWINDOWINFO pwi);
从MSDN documentation获取 GetWindowInfo函数:
BOOL WINAPI GetWindowInfo(
_In_ HWND hwnd,
_Inout_ PWINDOWINFO pwi
);
修改
正如答案评论中所提到的,第一个代码示例是正确的。第二个代码块是不正确的,因为通过指针传递和通过引用传递是不同的,并反映了我的基本误解。我在考虑使用C ++解除引用。有关详情,请参阅this问题。
答案 0 :(得分:1)
是的,您应该使用结构的ref
关键字。
首先,您可以在www.pinvoke.net上找到非常好的P / Invoke定义资源 - 这里记录了您正在处理的特定方法:http://www.pinvoke.net/default.aspx/user32.getwindowinfo。您会看到它是使用ref
关键字定义的。当您考虑在您链接的MSDN文档中将该方法记录为_Inout_
时,这是有意义的。
这样做的原因是ref
关键字将允许传递该引用并在调用方法获取更新/修改之前使用您正在处理的结构 - 而不是按原样传递它而从不传递看看方法实际上对它做了什么。换句话说,如果没有ref
关键字,您的代码将永远不会看到struct
调用中GetWindowInfo
所做的更改 - GetWindowInfo
将使用其“自己的”副本那种结构。
如果您想更多地了解为什么第二个版本不起作用,请查看JaredPar对What is the difference between a C# Reference and a Pointer?
的重要解释