Note that there are some explanatory texts on larger screens.

plurals
  1. POP/Invoke Interop Assistant: Is this actually correct?
    text
    copied!<p>I've got the following structs in C++: (Using pragma pack 1)</p> <pre><code>typedef struct _wfs_cdm_physicalcu { LPSTR lpPhysicalPositionName; CHAR cUnitID[5]; ULONG ulInitialCount; ULONG ulCount; ULONG ulRejectCount; ULONG ulMaximum; USHORT usPStatus; BOOL bHardwareSensor; } WFSCDMPHCU, * LPWFSCDMPHCU; typedef struct _wfs_cdm_cashunit { USHORT usNumber; USHORT usType; LPSTR lpszCashUnitName; CHAR cUnitID[5]; CHAR cCurrencyID[3]; ULONG ulValues; ULONG ulInitialCount; ULONG ulCount; ULONG ulRejectCount; ULONG ulMinimum; ULONG ulMaximum; BOOL bAppLock; USHORT usStatus; USHORT usNumPhysicalCUs; LPWFSCDMPHCU *lppPhysical; } WFSCDMCASHUNIT, * LPWFSCDMCASHUNIT; typedef struct _wfs_cdm_cu_info { USHORT usTellerID; USHORT usCount; LPWFSCDMCASHUNIT *lppList; } WFSCDMCUINFO, * LPWFSCDMCUINFO; </code></pre> <p>P/Invoke Interop Assistant gives me the following output:</p> <pre><code>[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet=System.Runtime.InteropServices.CharSet.Ansi, Pack = 1)] public struct WFSCDMPHCU { /// LPSTR-&gt;CHAR* [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] public string lpPhysicalPositionName; /// CHAR[5] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=5)] public string cUnitID; /// ULONG-&gt;unsigned int public uint ulInitialCount; /// ULONG-&gt;unsigned int public uint ulCount; /// ULONG-&gt;unsigned int public uint ulRejectCount; /// ULONG-&gt;unsigned int public uint ulMaximum; /// USHORT-&gt;unsigned short public ushort usPStatus; /// BOOL-&gt;int public int bHardwareSensor; } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet=System.Runtime.InteropServices.CharSet.Ansi, Pack = 1)] public struct WFSCDMCASHUNIT { /// USHORT-&gt;unsigned short public ushort usNumber; /// USHORT-&gt;unsigned short public ushort usType; /// LPSTR-&gt;CHAR* [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] public string lpszCashUnitName; /// CHAR[5] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=5)] public string cUnitID; /// CHAR[3] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=3)] public string cCurrencyID; /// ULONG-&gt;unsigned int public uint ulValues; /// ULONG-&gt;unsigned int public uint ulInitialCount; /// ULONG-&gt;unsigned int public uint ulCount; /// ULONG-&gt;unsigned int public uint ulRejectCount; /// ULONG-&gt;unsigned int public uint ulMinimum; /// ULONG-&gt;unsigned int public uint ulMaximum; /// BOOL-&gt;int public int bAppLock; /// USHORT-&gt;unsigned short public ushort usStatus; /// USHORT-&gt;unsigned short public ushort usNumPhysicalCUs; /// LPWFSCDMPHCU* public System.IntPtr lppPhysical; } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 1)] public struct WFSCDMCUINFO { /// USHORT-&gt;unsigned short public ushort usTellerID; /// USHORT-&gt;unsigned short public ushort usCount; /// LPWFSCDMCASHUNIT* public System.IntPtr lppList; } </code></pre> <p>However, when using Marshal.PtrToStruct (say, on WFSCDMCUINFO.lppList) I get garbage; when viewing memory using Visual Studio, I see the actual contents in another memory entry (not lppList per se).</p> <p>Are these conversions correct? Is my trust in P/Invoke Interop Assistant misplaced?</p> <p>EDIT:</p> <p>This is the code I use to Marshal to/from IntPtr. I know the Thread idea sucks, but I'll get to that later...</p> <pre><code> public static IntPtr GetIntPtr(this object obj) { try { var handle = GCHandle.Alloc(obj, GCHandleType.Pinned); var thread = new Thread(() =&gt; { Thread.Sleep(20000); handle.Free(); }); thread.Start(); return handle.AddrOfPinnedObject(); } catch (ArgumentException) { var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj)); Marshal.StructureToPtr(obj, ptr, false); return ptr; } } public static T FromIntPtr&lt;T&gt;(this IntPtr ptr) { if (ptr == IntPtr.Zero) return default(T); return (T) Marshal.PtrToStructure(ptr, typeof (T)); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload