C#調用C++ dll時,結構體引用傳參的方法


寫了一個C++的LogLog Logit 四參數等算法的接口dll,給C#調用,但是發現傳參有問題

extern "C" _declspec(dllexport)  bool TestFunc(EnumMethod eMethod, unsigned int uiPoints, const double *parA, const double *parB, STRUCTTEST &sTest)

 

前面的傳參非常好解決

枚舉本地自定義一個,兩個double指針直接ref傳參

 double[] rlu = new double[6];
            rlu[0] = 8759;
            rlu[1] = 39686;
            rlu[2] = 108791;
            rlu[3] = 473403;
            rlu[4] = 1679609;
            rlu[5] = 4103842;

            double[] cv = new double[6];
            cv[0] = 0;
            cv[1] = 3;
            cv[2] = 10;
            cv[3] = 50;
            cv[4] = 200;
            cv[5] = 600;
CalculationParm Cparms = new CalculationParm();
 bool rt = Calculation(ArithmeticMethod.Arithmetic_Method_Log_Log,
                6, ref cv[0], ref rlu[0], Cparms);

  直接傳參,結果結果並沒有根據實際情況變更.

根據相關資料,

在C/C++中,struct類型中的成員的一旦聲明,則實例中成員在內存中的布局(Layout)順序就定下來了,即與成員聲明的順序相同,並且在默認情況下總是按照結構中占用空間最大的成員進行對齊(Align);

然而在.net托管環境中,CLR提供了更自由的方式來控制struct中Layout:我們可以在定義struct時,在struct上運用StructLayoutAttribute特性來控制成員的內存布局。默認情況下,struct實例中的字段在棧上的布局(Layout)順序與聲明中的順序相同,即在struct上運用[StructLayoutAttribute(LayoutKind.Sequential)]特性,這樣做的原因是結構常用於和非托管代碼交互的情形。如果我們正在創建一個與非托管代碼沒有任何互操作的struct類型,我們很可能希望改變C#編譯器的這種默認規則,因此LayoutKind除了Sequential成員之外,還有兩個成員Auto和Explicit,給StructLayoutAttribute傳入LayoutKind.Auto可以讓CLR按照自己選擇的最優方式來排列實例中的字段;傳入LayoutKind.Explicit可以使字段按照我們的在字段上設定的FieldOffset來更靈活的設置字段排序方式,但這種方式也挺危險的,如果設置錯誤后果將會比較嚴重。

因此,把結構體顯示的聲明為  [StructLayout(LayoutKind.Sequential)]即可.

 

默認(LayoutKind.Sequential)情況下,CLR對struct的Layout的處理方法與C/C++中默認的處理方式相同,即按照結構中占用空間最大的成員進行對齊(Align); 
使用LayoutKind.Explicit的情況下,CLR不對結構體進行任何內存對齊(Align),而且我們要小心就是FieldOffset; 
使用LayoutKind.Auto的情況下,CLR會對結構體中的字段順序進行調整,使實例占有盡可能少的內存,並進行
4byte的內存對齊(Align)。

但似乎在vs2005中,默認並不是sequential而是auto


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM