2010-12-16 87 views
3

我的結構++是以下我想從C元帥一個結構到C#,不知道從哪裏用C開始

/* this structure contains the xfoil output parameters vs angle of attack */ 
    typedef struct xfoil_outputdata_struct 
    { 
    double *pAlfa; 
    double *pCL; 
    double *pCM; 
    double *pCDi; 
    double *pCDo; 
    double *pCPmax; 
    long nEntries; 
    } XFOIL_OUTPUT_DATA; 

    /* Here are the function prototypes for XFoil */ 
    __declspec(dllexport) XFOIL_OUTPUT_DATA *xfoilResults(); /* get output from xfoil */ 

我用XFoilResults拉這種結構回C#

我DLL Imports語句如下:

[DllImport("xfoilapi.dll")] 
     public static extern void xfoilResults(); 

這是正確的嗎?我無法控制C++代碼。我只需要能夠將結構拉入C#。 C#的結構我至今是以下

[StructLayout(LayoutKind.Sequential)] 
    public struct xfoilResults 
    { 
    IntPtr pAlfa; 
     IntPtr pCL; 
     IntPtr pCM; 
     IntPtr pCDi; 
     IntPtr pCDo; 
     IntPtr pCPmax; 
    long nEntries; 
    } 

我怎麼能填充這個C#結構與C++代碼的數據?

+0

有什麼部署方案?如果您可以在應用程序中支付額外的.dll文件,那麼使用C++/CLI來處理這些內容會讓您的生活更加愉快。它可以直接通過#include使用C++結構定義,使用C++語法提取數據,並將其填入一系列'System :: Generic :: Collections :: List '或.NET數組對象('cli :: array ')以供C#進一步使用。 – 2010-12-16 19:43:37

回答

2

StructLayout必須在一個類。

這應該做的伎倆:

[DllImport("xfoilapi.dll")] 
public static extern IntPtr GetXfoilResults(); 

[StructLayout(LayoutKind.Sequential)] 
public class XfoilResults 
{ 
    IntPtr pAlfa; 
    IntPtr pCL; 
    IntPtr pCM; 
    IntPtr pCDi; 
    IntPtr pCDo; 
    IntPtr pCPmax; 
    int nEntries; // thanks to guys for reminding me long is 4 bytes 
} 

XfoilResults xf == new XfoilResults(); 
Marshal.PtrToStructure(GetXfoilResults(), xf); 
+2

不應該是int nEntries,因爲C++中的'long'是32位? – Marlon 2010-12-16 19:40:10

+0

你是絕對正確的!我改變了它。 – Aliostad 2010-12-16 19:49:52

+0

只是挑剔。 StructLayout不需要在類上。它可以在結構上。 (檢查它的AttributeTargets。)兩者之間的區別在於你調用PtrToStructure的方式,因爲在你的例子中使用的重載修改了xf,在結構的情況下,xf通過值傳遞。另一個重載允許你創建並返回一個新的結構體。 (如我的答案)。 – 2010-12-16 19:55:36

2

首先,你的輸入函數的返回類型應該是IntPtr[MarshalAs(UnmanagedType.LPStruct)] xfoilResults_t

第二個重要注意事項是,如果xfoilResults()正在分配並填充該結構中的數據,那麼應該在某處使用第二個函數來清理該內存。您還必須導入並根據需要調用它,否則最終會發生內存泄漏。

如果你要手動名帥本(即進口返回一個IntPtr),你應該能夠使用

IntPtr retval = xfoilResults(); 
var results = (xfoilResults_t)Marshal.PtrToStructure(
             retVal, 
             typeof(xfoilResults_t)); 

//Do the following for each IntPtr field 
double[] pCL = new double[results.nEntries]; 
Marshal.Copy(results.pCL, pCL, 0, results.nEntries); 

//Don't forget to call whichever function is cleaning up the unmanaged memory.