寫了一個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