Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The simplest method of dealing with this type of problem is along the same lines as you might for a bit field, simply pack your data into a private member (or members if it is large) of the appropriate data type and then present public properties that unpack the data for you. The unpacking operations are extremely fast and will have little impact on performance. For your particular type the following is probably what you want:</p> <pre><code>public struct SomeStruct { private long data; public byte SomeByte { get { return (byte)(data &amp; 0x0FF); } } public int SomeInt { get { return (int)((data &amp; 0xFFFFFFFF00) &lt;&lt; 8); } } public short SomeShort { get { return (short)((data &amp; 0xFFFF0000000000) &lt;&lt; 40); } } public byte SomeByte2 { get { return (byte)((data &amp; unchecked((long)0xFF00000000000000)) &lt;&lt; 56); } } } </code></pre> <p>For some structures even this method is not workable due to the unfortunate way a structure has been defined. In those cases you will generally have to use a byte array as a blob of data from which the elements can be unpacked. </p> <p>EDIT: To expand on what I mean about structs that can't be handled using this simple method. When you can't do simple packing/unpacking like this you need to manually marshal the irregular struct . This can be done using manual methods at the point you call the pInvoked API or by using a custom marshaler. The following is an example of a custom marhsaler that can be easily adapted to on the spot manual marshaling. </p> <pre><code>using System.Runtime.InteropServices; using System.Threading; public class Sample { [DllImport("sample.dll")] public static extern void TestDataMethod([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(TestDataMarshaler))] TestDataStruct pData); } public class TestDataStruct { public byte data1; public int data2; public byte[] data3 = new byte[7]; public long data4; public byte data5; } public class TestDataMarshaler : ICustomMarshaler { //thread static since this could be called on //multiple threads at the same time. [ThreadStatic()] private static TestDataStruct m_MarshaledInstance; private static ICustomMarshaler m_Instance = new TestDataMarshaler(); public static ICustomFormatter GetInstance(string cookie) { return m_Instance; } #region ICustomMarshaler Members public void CleanUpManagedData(object ManagedObj) { //nothing to do. } public void CleanUpNativeData(IntPtr pNativeData) { Marshal.FreeHGlobal(pNativeData); } public int GetNativeDataSize() { return 21; } public IntPtr MarshalManagedToNative(object ManagedObj) { m_MarshaledInstance = (TestDataStruct)ManagedObj; IntPtr nativeData = Marshal.AllocHGlobal(GetNativeDataSize()); if (m_MarshaledInstance != null) { unsafe //unsafe is simpler but can easily be done without unsafe if necessary { byte* pData = (byte*)nativeData; *pData = m_MarshaledInstance.data1; *(int*)(pData + 1) = m_MarshaledInstance.data2; Marshal.Copy(m_MarshaledInstance.data3, 0, (IntPtr)(pData + 5), 7); *(long*)(pData + 12) = m_MarshaledInstance.data4; *(pData + 20) = m_MarshaledInstance.data5; } } return nativeData; } public object MarshalNativeToManaged(IntPtr pNativeData) { TestDataStruct data = m_MarshaledInstance; m_MarshaledInstance = null; //clear out TLS for next call. if (data == null) data = new TestDataStruct(); //if no in object then return a new one unsafe //unsafe is simpler but can easily be done without unsafe if necessary { byte* pData = (byte*)pNativeData; data.data1 = *pData; data.data2 = *(int*)(pData + 1); Marshal.Copy((IntPtr)(pData + 5), data.data3, 0, 7); data.data4 = *(long*)(pData + 12); data.data5 = *(pData + 20); } return data; } #endregion } </code></pre> <p>In the case of arrays of these structs you can't use custom marshaling unless the array size is fixed but it is relatively easy to manually marshal the array data as a whole using the same techniques.</p>
 

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