首页 / C# / C#面对“重载”的Win 32 函数
C#面对“重载”的Win 32 函数
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C#面对“重载”的Win 32 函数,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2845字,纯文字阅读大概需要5分钟。
内容图文
在Win32 Api中有很多添加/设置函数在参数上支持多种不同类型的结构体。这些参数定义为LPVOID* 或者LPBYTE,LPVOID*一般由Win32 分配内存空间,在C#从通过System.IntPtr进行遍历[1]。LPBYTE空间在函数调用的外部进行分配,之所以定义为LPBYTE,是因为这些结构体可能并不相同——属性、大小不同。那么在C#中如何处理这种LPBYTE接收多种结构体引用的Win32 Api?
先看一个Win 32 API的定义:
// The NetUserSetInfo function sets the parameters of a user account. // Syntax [2] NET_API_STATUS NetUserSetInfo( _In_ LPCWSTR servername, _In_ LPCWSTR username, _In_ DWORD level, _In_ LPBYTE buf, _Out_ LPDWORD parm_err ); // LPBYTE支持的结构体有二十多种 /* *buf部分类型说明 0 Specifies the user account name. The buf parameter points to a USER_INFO_0 structure. Use this structure to specify a new group name. For more information, see the following Remarks section. 1 Specifies detailed information about the user account. The buf parameter points to a USER_INFO_1 structure.
....
1005 Specifies a user privilege level. The buf parameter points to a USER_INFO_1005 structure.
..... * */
LPBYTE buf支持的类型多达二十多个,面对这种情况,一般可以有两种解决办法。LPBYTE是一个字节数组(栈或者堆)指针,在C#中对应的类型为System.UInt[]。但在此函数中,LPBYTE buf是指向结构体首地址的地址指针。所以第一种方法是直接传入IntPtr。IntPtr是一个神奇的类型,MSDN是这样介绍的[3]:
A platform-specific type that is used to represent a pointer or a handle.
用于表示指针或句柄的平台特定类型。
在Remark是这样说的:
The IntPtr type can be used by languages that support pointers, and as a common means of referring to data between languages that do and do not support pointers.
MSDN机器翻译:
IntPtr 语言中所支持的指针,并作为一种常见的方式来指代语言,并不支持指针之间的数据,则可以使用类型。
MSDN机器翻译我个人认为是错误的,我个人翻译为:
IntPtr可以被支持指针,或者那些不支持指针,而使用通常意义上的数据的引用做指针所做的事的各种(编程)语言使用。(.NET支持多种语言,有些语言支持指针。)
基于以上,第一种方法这是使用System.IntPtr来类型替换LPBYTE,支持多种变化的结构体Buf。那么该函数在C#中的定义即为:
[DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] internalstaticexternuint NetUserSetInfo( [MarshalAs(UnmanagedType.LPWStr)] string servername, [MarshalAs(UnmanagedType.LPWStr)] string username, uint level, IntPtr buf, uint parm_err);
第二种方法基于Win32 Api函数的“重载”——类似于通过参数实现的重载。如果在使用某一个函数时,不考虑其通用性而考虑具体性,可以直接将函数定义为具体的结构体类型。比如如下定义:
[DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] internalstaticexternuint NetUserSetInfo( [MarshalAs(UnmanagedType.LPWStr)] string servername, [MarshalAs(UnmanagedType.LPWStr)] string username, uint level, ref USER_INFO_1003 buf, uint parm_err); [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] internalstaticexternuint NetUserSetInfo( [MarshalAs(UnmanagedType.LPWStr)] string servername, [MarshalAs(UnmanagedType.LPWStr)] string username, uint level, ref USER_INFO_1017 buf, uint parm_err);
这两个函数在C#中属于重载函数,支持USER_INFO_1003 和 USER_INFO_1017两个类型。当需要较多的重载函数时,这种方法稍显冗余,使用IntPtr更加有弹性。
毕竟,Win32 只是想得到结构体的地址指针。使用具体类型的引用(ref)或者IntPtr都可以做到。
参考:
[1] 遍历LPVOID*, http://www.cnblogs.com/jjseen/p/win32_api.html
[2] NetSetUserInfo, https://msdn.microsoft.com/zh-cn/data/aa370659(v=vs.100)
[3] IntPtr结构, https://msdn.microsoft.com/zh-cn/library/system.intptr(v=vs.110).aspx
原文:http://www.cnblogs.com/jjseen/p/5745963.html
内容总结
以上是互联网集市为您收集整理的C#面对“重载”的Win 32 函数全部内容,希望文章能够帮你解决C#面对“重载”的Win 32 函数所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。