Note that there are some explanatory texts on larger screens.

plurals
  1. POConvert C Union to C# (Incorrectly Aligned)
    text
    copied!<p>I want to call the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363286%28v=vs.85%29.aspx" rel="nofollow">DhcpGetClientInfo</a> API from C# but I have a question on conversion of this C struct to C#:</p> <pre><code>typedef struct _DHCP_CLIENT_SEARCH_INFO { DHCP_SEARCH_INFO_TYPE SearchType; union { DHCP_IP_ADDRESS ClientIpAddress; DHCP_CLIENT_UID ClientHardwareAddress; LPWSTR ClientName; } SearchInfo; } DHCP_SEARCH_INFO, *LPDHCP_SEARCH_INFO; </code></pre> <p>I think the Correct conversion is this:</p> <pre><code>[StructLayout(LayoutKind.Explicit, Size=12)] public struct DHCP_SEARCH_INFO { [FieldOffset(0)] public DHCP_SEARCH_INFO_TYPE SearchType; [FieldOffset(4)] public DHCP_IP_ADDRESS ClientIpAddress; [FieldOffset(4)] public DHCP_BINARY_DATA ClientHardwareAddress; [FieldOffset(4), MarshalAs(UnmanagedType.LPWStr)] public string ClientName; }; </code></pre> <p>But that gives an System.TypeLoadException: Additional information: Could not load type 'Dhcpsapi.DHCP_SEARCH_INFO' from assembly 'ConsoleApplication3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 4 that is incorrectly aligned or overlapped by a non-object field.</p> <p>This is the conversion of the other types in case you want to compile:</p> <pre><code>public enum DHCP_SEARCH_INFO_TYPE : uint { DhcpClientIpAddress = 0, DhcpClientHardwareAddress = 1, DhcpClientName = 2 }; [StructLayout(LayoutKind.Sequential)] public struct DHCP_BINARY_DATA { public uint DataLength; public IntPtr Data; }; [StructLayout(LayoutKind.Sequential)] public struct DHCP_IP_ADDRESS { public UInt32 IPAddress; } </code></pre> <p><strong>EDIT:</strong></p> <p>I verified sizeof and offsets in C:</p> <pre><code>#pragma comment(lib,"Dhcpsapi.lib") int _tmain(int argc, _TCHAR* argv[]) { DHCP_SEARCH_INFO si; printf("sizeof(DHCP_SEARCH_INFO)=%d\n", sizeof(DHCP_SEARCH_INFO)); printf("ClientIpAddress offset=%d\n", (PBYTE)&amp;si.SearchInfo.ClientIpAddress - (PBYTE)&amp;si); printf("ClientHardwareAddress offset=%d\n", (PBYTE)&amp;si.SearchInfo.ClientHardwareAddress - (PBYTE)&amp;si); printf("ClientName offset=%d\n", (PBYTE)&amp;si.SearchInfo.ClientName - (PBYTE)&amp;si); return 0; } </code></pre> <p>Output is:</p> <pre><code>sizeof(DHCP_SEARCH_INFO)=12 ClientIpAddress offset=4 ClientHardwareAddress offset=4 ClientName offset=4 </code></pre> <p><strong>EDIT:</strong> Based on Camford's answer I declared the struct as below. Using sizeof should make it correct for x64 as well.</p> <pre><code>[StructLayout(LayoutKind.Explicit, Size=12)] public struct DHCP_SEARCH_INFO { [FieldOffset(0)] public DHCP_SEARCH_INFO_TYPE SearchType; [FieldOffset(sizeof(DHCP_SEARCH_INFO_TYPE))] public DHCP_IP_ADDRESS ClientIpAddress; [FieldOffset(sizeof(DHCP_SEARCH_INFO_TYPE))] public IntPtr ClientName; [FieldOffset(sizeof(DHCP_SEARCH_INFO_TYPE))] public DHCP_BINARY_DATA ClientHardwareAddress; }; </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