2010-12-16 47 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.