Fighting Ant

Ant can be great while elephant can be chickenshit

导航

System.Runtime.InteropServices浅见

Posted on 2008-03-31 18:09  Nillson  阅读(16508)  评论(1编辑  收藏  举报

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; 
}

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();

一个将三个类综合运用的实例:调用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);
            }

        }

    }


}