c# 如何调用非托管函数2-传递结构和类
2009-09-26 08:02
351 查看
原文: 刘武|c# 如何调用非托管函数2-传递结构和类
在上一篇 c# 如何调用非托管函数 中介绍了调用非托管函数的简单方法,其中传递的都是简单的值类型,如uint等。本篇将介绍如何传递结构或类到非托管函数。
以系统函数 GetSystemTime 为例,以下分别演示了如何传递结构和类。
一 传递结构
参考MSDN可以知道他的定义为:
void WINAPI GetSystemTime(__out LPSYSTEMTIME lpSystemTime);
其中LPSYSTEMTIME 就是一个结构体:
C++-Code:
根据原始定义我们可以把它转成C#的形式(word类型相当于c#中的ushort)
C#-Code:
由于该结构是作为out参数传递的,因此在c#中我们必须通过引用来传递:
C#-Code:
以下是完整代码:
C#-Code:
调用起来也比较简单:
C#-Code:
二 传递类
对于以上的例子,我们也可以把结构改成类传递给非托管函数,因为类是引用类型,所以我们不再需要ref声明:
C#-Code:
注意这里只是一个特例,并不是所有的情况既可以定义成结构类型也可以定义成类类型,通常我们应遵循以下原则:
在非托管函数不要求任何间接寻址时使用按值传递的结构。
在非托管函数要求一级间接寻址时使用按引用传递或按类传递的结构。
在非托管函数要求二级间接寻址时使用按引用传递的类。
参考:
http://www.liuwu.net/post/how-to-invoke-unmanaged-code-in-csharp.aspx
http://msdn.microsoft.com/zh-cn/library/awbckfbz.aspx
http://msdn.microsoft.com/en-us/library/ms724390.aspx
在上一篇 c# 如何调用非托管函数 中介绍了调用非托管函数的简单方法,其中传递的都是简单的值类型,如uint等。本篇将介绍如何传递结构或类到非托管函数。
以系统函数 GetSystemTime 为例,以下分别演示了如何传递结构和类。
一 传递结构
参考MSDN可以知道他的定义为:
void WINAPI GetSystemTime(__out LPSYSTEMTIME lpSystemTime);
其中LPSYSTEMTIME 就是一个结构体:
C++-Code:
typedef struct _SYSTEMTIME { WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds; } SYSTEMTIME, *PSYSTEMTIME;
根据原始定义我们可以把它转成C#的形式(word类型相当于c#中的ushort)
C#-Code:
[StructLayout(LayoutKind.Sequential)] public struct SystemTime { public ushort wYear; public ushort wMonth; public ushort wDayOfWeek; public ushort wDay; public ushort wHour; public ushort wMinute; public ushort wSecond; public ushort wMilliseconds; }
由于该结构是作为out参数传递的,因此在c#中我们必须通过引用来传递:
C#-Code:
[DllImport("Kernel32.dll")] public static extern void GetSystemTime(ref SystemTime st);
以下是完整代码:
C#-Code:
public class Kernel32
{
[StructLayout(LayoutKind.Sequential)] public struct SystemTime { public ushort wYear; public ushort wMonth; public ushort wDayOfWeek; public ushort wDay; public ushort wHour; public ushort wMinute; public ushort wSecond; public ushort wMilliseconds; }
[DllImport("Kernel32.dll")] public static extern void GetSystemTime(ref SystemTime st);
}
调用起来也比较简单:
C#-Code:
private void btnGetSysTime_Click(object sender, EventArgs e) { Kernel32.SystemTime sysTime = new Kernel32.SystemTime(); Kernel32.GetSystemTime(ref sysTime); MessageBox.Show(string.Format("{0}-{1}-{2} {3}:{4}:{5}", sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond)); }
二 传递类
对于以上的例子,我们也可以把结构改成类传递给非托管函数,因为类是引用类型,所以我们不再需要ref声明:
C#-Code:
public class Kernel32 { [StructLayout(LayoutKind.Sequential)] public class SystemTime { public ushort wYear; public ushort wMonth; public ushort wDayOfWeek; public ushort wDay; public ushort wHour; public ushort wMinute; public ushort wSecond; public ushort wMilliseconds; } [DllImport("Kernel32.dll")] public static extern void GetSystemTime(SystemTime st); }
注意这里只是一个特例,并不是所有的情况既可以定义成结构类型也可以定义成类类型,通常我们应遵循以下原则:
在非托管函数不要求任何间接寻址时使用按值传递的结构。
在非托管函数要求一级间接寻址时使用按引用传递或按类传递的结构。
在非托管函数要求二级间接寻址时使用按引用传递的类。
参考:
http://www.liuwu.net/post/how-to-invoke-unmanaged-code-in-csharp.aspx
http://msdn.microsoft.com/zh-cn/library/awbckfbz.aspx
http://msdn.microsoft.com/en-us/library/ms724390.aspx
相关文章推荐
- c# 如何调用非托管函数2-传递结构和类
- 如何调用需要指向包含字符串的结构的指针的非托管函数
- c# 如何调用非托管函数 (转)
- c# 如何调用非托管函数3-实现回调函数
- c# 如何调用非托管函数
- Sql2012如何将远程服务器数据库及表、表结构、表数据导入本地数据库 自定义日志记录功能,按日记录,很方便 C#常量和字段以及各种方法的语法总结 类型,对象,线程栈,托管堆在运行时的关系,以及clr如何调用静态方法,实例方法,和虚方法 asp.net webapi 自定义身份验证
- c# 如何调用非托管函数3-实现回调函数
- C#如何调用批处理文件 C#如何向批处理文件传递多个参数
- 如何用C#程序调用bat文件的同时向bat文件传递类似字符串这样的参数?
- 如何:了解向方法传递结构和向方法传递类引用之间的区别(C# 编程指南)
- c# 如何调用非托管函数
- C#调用C++的dll关于复杂结构的参数传递
- C#调用webservice 时如何传递实体对象
- C#中如何处理Delphi的REST Server返回的复杂结构资料
- 如何利用MFC编写的.exe调用C#编写的dll动态库
- [C#] 如何调用Windows系统发送错误API
- C# 控制台程序下,如何启用Timer 及多次调用后如何更改周期
- 5 在C#中如何调用基类构造器
- 如何在XSLT里调用C#的代码
- 如何在调用线程的时候传递参数