System.Runtime.InteropServices提供了相应的类或者方法来支持托管/非托管模块间的互相调用。
System.Runtime.InteropServices中几个比较重要的类:
DllImportAttribute : 该类提供对非托管动态链接库进行引用的方法,并告诉我们的编译器该程序的静态入口点是非托管的动态连接库,它的静态属性提供了对非托管动态链接库进行调用所必需的信息,作为最基本的要求,该类应该定义提供调用的非托管动态链接库的名称。成员详细信息
StructLayoutAttribute: 该类使得用户可以控制类或结构的数据字段的物理布局。
[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public class MySystemTime
{
[FieldOffset(0)]public ushort wYear;
[FieldOffset(2)]public ushort wMonth;
[FieldOffset(4)]public ushort wDayOfWeek;
[FieldOffset(6)]public ushort wDay;
[FieldOffset(8)]public ushort wHour;
[FieldOffset(10)]public ushort wMinute;
[FieldOffset(12)]public ushort wSecond;
[FieldOffset(14)]public ushor wMilliseconds;
}
public class MySystemTime
{
[FieldOffset(0)]public ushort wYear;
[FieldOffset(2)]public ushort wMonth;
[FieldOffset(4)]public ushort wDayOfWeek;
[FieldOffset(6)]public ushort wDay;
[FieldOffset(8)]public ushort wHour;
[FieldOffset(10)]public ushort wMinute;
[FieldOffset(12)]public ushort wSecond;
[FieldOffset(14)]public ushor wMilliseconds;
}
MarshalAsAttribute : 指示如何在托管代码和非托管代码之间封送数据。下面是MSDN给出的示例代码:
[C#]
//Applied to a parameter.
public void M1 ([MarshalAs(UnmanagedType.LPWStr)]String msg);
//Applied to a field within a class.
class MsgText {
[MarshalAs(UnmanagedType.LPWStr)] Public String msg;
}
//Applied to a return value.
[return: MarshalAs(UnmanagedType.LPWStr)]
public String GetMessage();
//Applied to a parameter.
public void M1 ([MarshalAs(UnmanagedType.LPWStr)]String msg);
//Applied to a field within a class.
class MsgText {
[MarshalAs(UnmanagedType.LPWStr)] Public String msg;
}
//Applied to a return value.
[return: MarshalAs(UnmanagedType.LPWStr)]
public String GetMessage();
一个将三个类综合运用的实例:调用kernel32.dll中的非托管方法"GetSystemTime"将系统时间返回给定制的类MySystemTime并执行输出.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace DllImportTest
{
/// <summary>
/// 定义一个用于接收非托管API方法返回值的类
/// StructLayout定义了该类的各个成员在物理上的排列方式
/// </summary>
[StructLayout(LayoutKind.Explicit, Size = 16, CharSet = CharSet.Ansi)]
public class MySystemTime
{
[FieldOffset(0)]
public ushort wYear;
[FieldOffset(2)]
public ushort wMonth;
[FieldOffset(4)]
public ushort wDayOfWeek;
[FieldOffset(6)]
public ushort wDay;
[FieldOffset(8)]
public ushort wHour;
[FieldOffset(10)]
public ushort wMinute;
[FieldOffset(12)]
public ushort wSecond;
[FieldOffset(14)]
public ushort wMilliseconds;
}
/// <summary>
/// 用LibWrapper的静态方法来调用非托管API方法"GetSystemTime"
/// </summary>
class LibWrapper
{
[DllImport("kernel32.dll", EntryPoint = "GetSystemTime")]
//如果定义的方法名称与要进行封装的非托管API方法不同则需要在DLLImport中指定入口点.
public static extern void gettime([MarshalAs(UnmanagedType.LPStruct)]MySystemTime st);
}
class TestApplication
{
public static void Main()
{
try
{
MySystemTime sysTime = new MySystemTime();
//LibWrapper.GetSystemTime(sysTime);
LibWrapper.gettime(sysTime);
Console.WriteLine("The System time is {0}/{1}/{2} {3}:{4}:{5}", sysTime.wDay,
sysTime.wMonth, sysTime.wYear, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
}
catch (TypeLoadException e)
{
Console.WriteLine("TypeLoadException : " + e.Message);
}
catch (Exception e)
{
Console.WriteLine("Exception : " + e.Message);
}
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace DllImportTest
{
/// <summary>
/// 定义一个用于接收非托管API方法返回值的类
/// StructLayout定义了该类的各个成员在物理上的排列方式
/// </summary>
[StructLayout(LayoutKind.Explicit, Size = 16, CharSet = CharSet.Ansi)]
public class MySystemTime
{
[FieldOffset(0)]
public ushort wYear;
[FieldOffset(2)]
public ushort wMonth;
[FieldOffset(4)]
public ushort wDayOfWeek;
[FieldOffset(6)]
public ushort wDay;
[FieldOffset(8)]
public ushort wHour;
[FieldOffset(10)]
public ushort wMinute;
[FieldOffset(12)]
public ushort wSecond;
[FieldOffset(14)]
public ushort wMilliseconds;
}
/// <summary>
/// 用LibWrapper的静态方法来调用非托管API方法"GetSystemTime"
/// </summary>
class LibWrapper
{
[DllImport("kernel32.dll", EntryPoint = "GetSystemTime")]
//如果定义的方法名称与要进行封装的非托管API方法不同则需要在DLLImport中指定入口点.
public static extern void gettime([MarshalAs(UnmanagedType.LPStruct)]MySystemTime st);
}
class TestApplication
{
public static void Main()
{
try
{
MySystemTime sysTime = new MySystemTime();
//LibWrapper.GetSystemTime(sysTime);
LibWrapper.gettime(sysTime);
Console.WriteLine("The System time is {0}/{1}/{2} {3}:{4}:{5}", sysTime.wDay,
sysTime.wMonth, sysTime.wYear, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
}
catch (TypeLoadException e)
{
Console.WriteLine("TypeLoadException : " + e.Message);
}
catch (Exception e)
{
Console.WriteLine("Exception : " + e.Message);
}
}
}
}