zoukankan      html  css  js  c++  java
  • 关于[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] 的解释

    关于[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] 的解释

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] 

    这是C#引用非托管的C/C++的DLL的一种定义定义结构体的方式,主要是为了内存中排序,LayoutKind有两个属性Sequential和Explicit

    Sequential表示顺序存储,结构体内数据在内存中都是顺序存放的Explicit表示精确布局,需要用FieldOffset()设置每个成员的位置这都是

    为了使用非托管的指针准备的,知道什么意思就行,C#的CLR提供了更为灵活的自动管理方式,所以对C#来说可有可无。

    CharSet=CharSet.Ansi表示编码方式

    http://blog.csdn.net/masterft/article/details/1699009

    http://www.cnblogs.com/lonelyDog/archive/2012/02/02/2335432.html

    http://www.cnblogs.com/namek/archive/2010/08/26/1808773.html

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

    结论:
            默认(LayoutKind.Sequential)情况下,CLR对struct的Layout的处理方法与C/C++中默认的处理方式相同,即按照结构中占用空间最大的成员进行对齐(Align);
            使用LayoutKind.Explicit的情况下,CLR不对结构体进行任何内存对齐(Align),而且我们要小心就是FieldOffset;
            使用LayoutKind.Auto的情况下,CLR会对结构体中的字段顺序进行调整,使实例占有尽可能少的内存,并进行4byte的内存对齐(Align)。

     

    最后一个是比较详细的介绍了平台调用的结构体对齐和内存布局

    第二:特殊的情况下,C++代码使用#pragma pack(n)改变了边界对齐。这里要使用C#要使用   [StructLayout(LayoutKind.Sequential, Pack = N)] 对齐,否则出错。

    http://www.cnblogs.com/namek/archive/2010/08/26/1808773.html

  • 相关阅读:
    java的应用项目
    项目评审ppt的纲要
    Spark环境搭建
    spark 环境搭建坑
    redis cluster 实现
    hadoop环境搭建编译
    centos 网络配置
    自定义shell开头PS1
    Centos. Mac 通过nfs 搭建共享目录
    mac系统中实现vitualBox中访问内网端口
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/12081783.html
Copyright © 2011-2022 走看看