2010-11-05 5 views
4

В C# 4.0, у меня естьC#: Преобразование Список простых структур в байт []

List<HSZPAIR> myList 

с тремя элементами где HSZPAIR структура определяется по формуле:

[StructLayout(LayoutKind.Sequential)] 
public struct HSZPAIR 
{ 
    public IntPtr hszSvc; 
    public IntPtr hszTopic; 
} 

Как создать массив байтов для всего myList? В C++ вы можете просто передать массив массивов в массив байтов. Я не уверен, как это сделать на C#.

Я использую старую функцию Windows API в библиотеке DDEML, для которой требуется массив байтов и количество элементов в массиве в качестве аргументов. Если вы заинтересованы в более фона, функция API является:

[DllImport("user32.dll", EntryPoint="DdeCreateDataHandle", 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. Аргумент pSrc представляет собой массив байтов структур HSZPAIR. Размер массива - аргумент cb.

+0

Мне удалось преобразовать одну структуру в массив байтов, учитывая учебное пособие по адресу http://www.developerfusion.com/article/84519/mastering-structs-in-c/. Преобразование всего списка структур в массив байтов - это то, что бросает меня за цикл. – dmjones

ответ

1

Преобразование структуры в массив байтов является болезненным. Вы должны сериализовать это самостоятельно. Но это может и не понадобиться.

Учитывая список:

List<HSZPAIR> myList; 

Вы можете получить массив, вызвав ToArray:

HSZPAIR[] myArray = myList.ToArray(); 

Теперь изменить свой управляемый прототип, так что он принимает HSZPAIR[], а не byte[]:

public static extern IntPtr DdeCreateDataHandle(
    int idInst, HSZPAIR[] pSrc, int cb, int cbOff, IntPtr hszItem, int wFmt, int afCmd); 

Это должно сработать. В конце концов, как вы указали, массив из HSZPAIR действительно представляет собой просто массив байтов.

+0

Мне нравится идея, но функция DdeCreateDataHandle - это своего рода функция общего назначения, предназначенная для преобразования массивов данных многих типов в указатель для других функций DDE. Если я изменю объявление, это может нарушить эти другие обычаи. Предполагается, что функция, которая принимает IntPtr, созданный DdeCreateDataHandle, должна знать, какой тип структуры данных. – dmjones

+0

Кроме того, у меня нет достаточной репутации для того, чтобы продвинуть вас еще, но вернусь и дам вам шанс, как только я это сделаю. – dmjones

+0

@dmjones: вы можете найти то, что ищете, в массивах маршалингов на http://msdn.microsoft.com/en-us/library/aa719546(v=VS.71).aspx. Похоже, страница сломана, так как примеры C# смешиваются с примерами VB. Но там они показывают, как массировать массивы несколькими способами. –

1

Я считаю, что вам нужно определить тип pSrc в объявлении extern как IntPtr, а не byte [].

+0

После просмотра вашего комментария я просмотрел через google, что другие определили определение extern с помощью IntPtr или байта []. Но я не уверен, как использование IntPtr вместо байта [] приближает меня к передаче этого массива структур. (Кроме того, у меня нет достаточной репутации, чтобы продвигать вас еще, но вернусь и дам вам возвышение, как только я это сделаю). – dmjones

+0

@dmjones: IntPtr имеет немного «привилегированного статуса» внутри C#; в принципе, он «просто работает». –

+0

Я попробую, спасибо. – dmjones

1

Я думаю, вы можете использовать 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; 
} 

Что касается самого списка, его необходимо будет сериализовать отдельно.

+0

Это очень похоже на то, что я использовал из Mastering Structs в C# link в моем исходном сообщении для маршалинга одной структуры. Я уверен, что другие оценят эту информацию. – dmjones