In C# 4.0, say I have
List<HSZPAIR> myList
with three elements where the HSZPAIR struct is defined by:
[StructLayout(LayoutKind.Sequential)]
public struct HSZPAIR
{
public IntPtr hszSvc;
public IntPtr hszTopic;
}
How do I create a byte array for the entire myList? In C++, you could just cast as array of structs down to a byte array. I'm not sure how to do that in C#.
I'm using an old Windows API function in the DDEML library that requires a byte array and the number of elements in the array as arguments. If you are interested in more background, the API function is:
[DllImport("user32.dll", EntryPoint="DdeCre开发者_StackOverflowateDataHandle", CharSet=CharSet.Ansi)]
public static extern IntPtr DdeCreateDataHandle(int idInst, byte[] pSrc, int cb, int cbOff, IntPtr hszItem, int wFmt, int afCmd);
Here is it's documentation on MSDN. The pSrc argument is the byte array of HSZPAIR structs. The size of the array is the cb argument.
Converting a struct to an array of bytes is kind of painful. You have to serialize it yourself. But it might not be necessary.
Given your list:
List<HSZPAIR> myList;
You can get an array by calling ToArray
:
HSZPAIR[] myArray = myList.ToArray();
Now, change your managed prototype so that it takes an HSZPAIR[]
rather than a byte[]
:
public static extern IntPtr DdeCreateDataHandle(
int idInst, HSZPAIR[] pSrc, int cb, int cbOff, IntPtr hszItem, int wFmt, int afCmd);
That should work. After all, as you pointed out, an array of HSZPAIR
really is just an array of bytes.
I think you can use Marshal.StructureToPtr.
static byte[] StructureToByteArray(object obj)
{
int length = Marshal.SizeOf(obj);
byte[] data = new byte[length];
IntPtr ptr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(obj, ptr, true);
Marshal.Copy(ptr, data, 0, length);
Marshal.FreeHGlobal(ptr);
return data;
}
As for the list itself, it will have to be serialized separately.
I believe you need to define the type of the pSrc in the extern declaration as IntPtr, instead of byte[].
精彩评论