• StructLayout特性、、、MashalAs


    公共语言运行库利用StructLayoutAttribute控制类或结构的数据字段在托管内存中的物理布局,即类或结构需要按某种方式排列。如果要将类传递给需要指定布局的非托管代码,则显式控制类布局是重要的。它的构造函数中用
    LayoutKind值初始化 StructLayoutAttribute 类的新实例。 LayoutKind.Sequential 用于强制将成员按其出现的顺序进行顺序布局。

    StructLayout特性允许我们控制Structure语句块的元素在内存中的排列方式,以及当这些元素被传递给外部DLL时,运行库排列这些元素的方式。

    可以通过System.Runtime.InteropServices.StructLayout  
    特性精确的控制每一个结构成员的位置。
    System.Runtime.InteropServices.StructLayout  
    允许的值有StructLayout.Auto   StructLayout.Sequential  
    StructLayout.Explicit.
        
    1.Sequential,顺序布局,比如
    struct
    S1
    {
      int a;
      int b;
    }
    那么默认情况下在内存里是先排a,再排b
    也就是如果能取到a的地址,和b的地址,则相差一个int类型的长度,4字节
    [StructLayout(LayoutKind.Sequential)]

    struct S1
    {
      int a;
      int
    b;
    }
    这样和上一个是一样的.因为默认的内存排列就是Sequential,也就是按成员的先后顺序排列.
    2.Explicit,精确布局
    需要用FieldOffset()设置每个成员的位置
    这样就可以实现类似c的公用体的功能
    [StructLayout(LayoutKind.Explicit)]

    struct S1
    {
      [FieldOffset(0)]
      int a;
      [FieldOffset(0)]
       int b;
    }
    这样a和b在内存中地址相同

     StructLayout特性支持三种附加字段:CharSet、Pack、Size。    
    ·  
    CharSet定义在结构中的字符串成员在结构被传给DLL时的排列方式。可以是Unicode、Ansi或Auto。    
      默认为Auto,在WIN
      NT/2000/XP中表示字符串按照Unicode字符串进行排列,在WIN   95/98/Me中则表示按照ANSI字符串进行排列。    
    ·  
    Pack定义了结构的封装大小。可以是1、2、4、8、16、32、64、128或特殊值0。特殊值0表示当前操作平台默认的压缩大小。    
     

      [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct LIST_OPEN
        {
            public int dwServerId;
            public int dwListId;
            public System.UInt16 wRecordSize;
            public System.UInt16 wDummy;
            public int dwFileSize;
            public int dwTotalRecs;
            public NS_PREFETCHLIST sPrefetch;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
            public string szSrcMach;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
            public string szSrcComp;
        }


    此例中用到MashalAs特性,它用于描述字段、方法或参数的封送处理格式用它作为参数前缀并指定目标需要的数据类型。
    例如,以下代码将两个参数作为数据类型长指针封送给 Windows API 函数的字符串 (LPStr):
    [MarshalAs(UnmanagedType.LPStr)]
    String existingfile;
    [MarshalAs(UnmanagedType.LPStr)]
    String newfile;

    [DllImport("coredll.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool ReadMsgQueue(IntPtr hMsgQ, out POWER_BROADCAST BroadCast, uint cbBufferSize, out uint lpNumberOfBytesRead, uint

     

    dwTimeout, out uint pdwFlags);注意结构作为参数时候,一般前面要加上ref修饰符,否则会出现错误:对象的引用没有指定对象的实例。
    [DllImport( "kernel32", EntryPoint="GetVersionEx" )]
    public static extern bool GetVersionEx2( ref OSVersionInfo2 osvi );


    转自:

    http://www.cnblogs.com/JessieDong/archive/2009/07/21/1527553.html
  • 相关阅读:
    [转]C#汉字转拼音的源码
    [转]C# DES 加密/解密类库,支持文件和中文/UNICODE字符,返回BASE64编码字符串
    48瓶子,48种性格
    “识谎”36计
    巧克力有益智商 经常吃可提高大脑计算能力
    调用方未由服务进行身份验证
    揭秘人体24小时使用手册
    [转]C#实现人民币金额小写转大写的代码
    转一篇绝对详细的手工构造PE文件教程
    bat 查找某个进程的ID号
  • 原文地址:https://www.cnblogs.com/KimhillZhang/p/2547590.html
Copyright © 2020-2023  润新知