p/invoke碎片--對類的封送處理

主要是看默認封送處理行爲函數

按類成員的類型是否爲「可直接傳遞到非託管內存」的類型來分類;按照成員中是否有「可直接傳遞到非託管內存」的類型來討論。spa

  全部成員都是「可直接傳遞到非託管內存」的類型指針

  託管代碼和非託管代碼:code

    //託管代碼       
            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\n",cs->a);
    printf("%lf\n",cs->d);
    cs->a=100;
}

   下斷點,在DoClassStruct(cs);處,發現cs的地址是0x01bcbaa0;進入 非託管函數中,下斷點,發現cs的地址不變。以下:blog

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 。內存

  結論:若是類的字段都是「可直接傳遞到非託管代碼中」的類型,那麼傳遞是引用,或者說是指針。這是在非託管代碼中的修改也會反映到託管代碼中了。這個過程就是鎖定string

 類的成員不包含「非可直接傳遞到非託管代碼中」的類型it

   看下面一個例子,知足條件的類型有bool和string類型等。class

            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\n",cs->a);
    printf("%lf\n",cs->d);
    cs->a=100;
}

 

   經過跟蹤發現,依然使用普通結構體的過程:在非託管內存中開闢空間---把託管內存中數據複製一份到非託管內存M-----內存M的地址做爲參數傳遞給函數---一切的操做都是圍着內存M進行。 可想而知,最後的結果不會反映到託管內存中去。引用

相關文章
相關標籤/搜索