开发者

I'm trying to marshal a struct from C to C#, not sure where to start

开发者 https://www.devze.com 2023-01-31 12:44 出处:网络
My struct in C++ is the following /* this structure contains the xfoil output parameters vs angle of attack */

My struct in C++ is the following

 /* 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 */

I use XFoilResults to pull this structure back into C#

My DLL Imports statement is the following:

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

Is this correct? I have no control over the C++ code. I just need to be able to pull the struct into C#. The C# struct I have so far is the following

[StructLayout(LayoutKind.Sequential)]
    public  struct xfoilResults
    {
   开发者_运维百科  IntPtr pAlfa;
        IntPtr pCL;
        IntPtr pCM;
        IntPtr pCDi;
        IntPtr pCDo;
        IntPtr pCPmax;
     long nEntries;
    }

How can I populate this C# structure with the data from the C++ code?


StructLayout must be on a class.

This should do the trick:

[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);


Firstly, the return type of your imported function should be either IntPtr or [MarshalAs(UnmanagedType.LPStruct)] xfoilResults_t.

A second important note is that, if xfoilResults() is allocating and populating the data in that struct, there should somewhere be a second function to clean up that memory. You must also import that - and call it as necessary, or you will end up with memory leaks.

If you're going to marshal this manually (ie, the import returns an IntPtr), You should be able to use

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.
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号