3

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?

1
  • What's the deployment scenario? If you can afford an extra .dll file in your application, then using C++/CLI for this stuff will make your life much more pleasant. It can use the C++ struct definition directly via #include, use the C++ syntax for pulling out the data, and stuff it into a series of System::Generic::Collections::List<double> or .NET array objects (cli::array<double>) for further use from C#. Commented Dec 16, 2010 at 19:43

2 Answers 2

2

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); 
Sign up to request clarification or add additional context in comments.

2 Comments

Shouldn't it be int nEntries, since a 'long' in C++ is 32-bits?
Just nitpicking. StructLayout does not need to be on a class. It can be on a struct. (Check the AttributeTargets of it.) The difference between the two is the way you call PtrToStructure, because the overload used in your example modifies xf, which is passed by value in the case of a struct. Another overload allows you to create and return a new struct. (As in my answer).
2

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. 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.