zoukankan      html  css  js  c++  java
  • p/invoke碎片--对类的封送处理

    主要是看默认封送处理行为

    按类成员的类型是否为“可直接传递到非托管内存”的类型来分类;按照成员中是否有“可直接传递到非托管内存”的类型来讨论。

      所有成员都是“可直接传递到非托管内存”的类型

      托管代码和非托管代码:

        //托管代码       
                ClassStruct cs = new ClassStruct();
                cs.a = 90;
                cs.d = 23;
                DoClassStruct(cs);
    
                Console.Read();
            }
    
            [StructLayout(LayoutKind.Sequential)]
            class ClassStruct
            {
                public int a;
                public double d;
            }
    、、、、、、、、、、、////////////非托管代码
    typedef struct 
    {
        int a;
        double d;
    }CLASSSTRUCT;

    extern "C" __declspec(dllexport) void DoClassStruct(CLASSSTRUCT *cs)
    {
        printf("%d ",cs->a);
        printf("%lf ",cs->d);
        cs->a=100;
    }

       下断点,在DoClassStruct(cs);处,发现cs的地址是0x01bcbaa0;进入 非托管函数中,下断点,发现cs的地址不变。如下:

    0x01BCBAA0  5a 00 00 00 00 00 00 00 00 00 00 00 00 00 37 40  Z.............7@   其中的5a是指90,后面8位是指double值23.0 。

      结论:如果类的字段都是“可直接传递到非托管代码中”的类型,那么传递是引用,或者说是指针。这是在非托管代码中的修改也会反映到托管代码中了。这个过程就是锁定

     类的成员不包含“非可直接传递到非托管代码中”的类型

       看下面一个例子,满足条件的类型有bool和string类型等。

                cs.a = 90;
                cs.d = 23;
                cs.str = "abcd";
                DoClassStruct(cs);
                Console.WriteLine(cs.a);
    
                Console.Read();
            }
    
            [StructLayout(LayoutKind.Sequential)]
            class ClassStruct
            {
                public int a;
                public double d;
                public string str;
            }
    /////////////////////////////非托管代码
    typedef struct 
    {
        int a;
        double d;
        char *pStr;
    }CLASSSTRUCT;
    
    extern "C" __declspec(dllexport) void DoClassStruct(CLASSSTRUCT *cs)
    {
        printf("%d
    ",cs->a);
        printf("%lf
    ",cs->d);
        cs->a=100;
    }

       通过跟踪发现,依然使用普通结构体的过程:在非托管内存中开辟空间---把托管内存中数据复制一份到非托管内存M-----内存M的地址作为参数传递给函数---一切的操作都是围着内存M进行。 可想而知,最后的结果不会反映到托管内存中去。

  • 相关阅读:
    Confluence 6 连接到一个 LDAP 目录
    Confluence 6 LDAP 成员结构设置
    Confluence 6 LDAP 用户组结构设置
    Confluence 6 LDAP 用户结构设置
    Confluence 6 LDAP 高级设置
    Confluence 6 自动添加用户到用户组
    Confluence 6 权限设置
    一个小白的测试环境docker化之路
    客户端SDK测试思路
    限时购校验小工具&dubbo异步调用实现限
  • 原文地址:https://www.cnblogs.com/ddx-deng/p/3886414.html
Copyright © 2011-2022 走看看