PDA

Показать полную графическую версию : [решено] C# to C++ dll: Маршалинг(?) массива структур


XCodeR
20-01-2010, 17:57
Всем доброе время суток!
Столкнулся с проблемой, которую не могу понять и соотвественно решить.

Имеется dll, написанная на C++ (исодный код мне не известен).
Обращаюсь к функциям из программы, написанной C#
Имеются следующий функции (описание C++, Interop C#)


//C++
SDKIMPORT_ SDKEXPORT_ DWORD sdkUpdateBoards( DWORD dwBoardsCount, sdkBoardStatus *lpBoardStatus[]);
-------------------
//C#
[DllImport(DLLPath, CharSet = CharSet.Auto, EntryPoint = "sdkUpdateBoards")]
static public extern UInt32 sdkUpdateBoards(UInt32 BoardsCount, ref tagsdkBoardStatus[] BoardStatus);
Описание структуры:

//C++
typedef struct tagsdkBoardStatus
{
DWORD BoardId; // Идентификатор платы
DWORD OwnDriverId; // Идентификатор драйвера платы
DWORD Type; // Тип платы
DWORD Bus; // Тип шины платы
DWORD Status; // Состояние платы
DWORD BasePort; // Базовый порт платы
DWORD FactoryNumber; // Номер платы
DWORD FactoryVersion; // Версия платы
DWORD ResourceMode; // Ресурс платы
DWORD Lines; // Количество интерфейсных каналов
DWORD VoiceLines; // Количество голосовых каналов
DWORD ChannelsId[128]; // Идентификаторы каналов
BYTE LineTypes[128]; // Типы каналов платы
BYTE PossibleLineTypes[128]; // Возможные типы каналов платы
BYTE LineStatus[128]; // Состояние каналов платы
DWORD Cpus; // Количество сопроцессоров
BYTE E1Present; // Наличие на плате мезонина Е1
DWORD PciCtrlPort;
BOOL SCBus;
BOOL SCBusMaster;
BOOL IrqMaster;
DWORD E1Lines;
DWORD E1MajorVersion;
DWORD E1MinorVersion;
DWORD E1STS;
}sdkBoardStatus;
//C#
public struct tagsdkBoardStatus
{
public UInt32 BoardId; // Идентификатор платы
public UInt32 OwnDriverId; // Идентификатор драйвера платы
public UInt32 Type; // Тип платы
public UInt32 Bus; // Тип шины платы
public UInt32 Status; // Состояние платы
public UInt32 BasePort; // Базовый порт платы
public UInt32 FactoryNumber; // Номер платы
public UInt32 FactoryVersion; // Версия платы
public UInt32 ResourceMode; // Ресурс платы
public UInt32 Lines; // Количество интерфейсных каналов
public UInt32 VoiceLines; // Количество голосовых каналов
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public UInt32[] ChannelsId; // Идентификаторы каналов
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public byte[] LineTypes; // Типы каналов платы
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public byte[] PossibleLineTypes; // Возможные типы каналов платы
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public byte[] LineStatus; // Состояние каналов платы
public UInt32 Cpus; // Количество сопроцессоров
public byte E1Present; // Наличие на плате мезонина Е1
public UInt32 PciCtrlPort;
public bool SCBus;
public bool SCBusMaster;
public bool IrqMaster;
public UInt32 E1Lines;
public UInt32 E1MajorVersion;
public UInt32 E1MinorVersion;
public UInt32 E1STS;

};

Код в котром "ошибка"
//C#
[MarshalAs(UnmanagedType.LPArray, SizeConst = 32)]
public static tagsdkBoardStatus[] BoardStatus; //Статус плат
BoardStatus = new tagsdkBoardStatus[2];
f = sdkUpdateBoards(BoardsCount, ref BoardStatus);

В итоге в BoardStatus только 1 элемента, когда должно быть 2.
-------

Извиняюсь, за столько скомконное изложение, но по окончанию рабочего дня мозг медленно плавится (((

XCodeR
21-01-2010, 10:19
Господа, очень надеюсь на вашу помощь!
Хех, я смотрю я уже не Контрибьютор )

XCodeR
21-01-2010, 13:58
Спасибо всем! вопрос снят.
Нашелся более лаконичный метод.

Небольшой сниппет для будущих поколений:
1. Convert IntPtr to array of struct(для поиска IntPtr2array)
public static Array PtrToArray(Type structureType,IntPtr arrayPtr,int length)
{
if (structureType == null)
throw new ArgumentNullException("structureType");
if (!structureType.IsValueType)
throw new ArgumentException("Only struct types are supported.", "structureType");
if (length < 0)
throw new ArgumentOutOfRangeException("length", length, "length must be equal to or greater than zero.");
if (arrayPtr == IntPtr.Zero)
return null;
int size = Marshal.SizeOf(structureType);
Array array = Array.CreateInstance(structureType, length);
for (int i = 0; i < length; i++)
{
IntPtr offset = new IntPtr((long)arrayPtr + (size * i));
object value = Marshal.PtrToStructure(offset, structureType);
array.SetValue(value, i);
}
return array;
}

Если интересует, то могу оформить небольшую статью по маршалингу типов и вообще использованию сишных библиотек под .Net.

А вообще было приятно снова посетить наш форму. опять таки давно не был здесь

*Сниппет не относится напрямую к поставленному вопросы в теме

Delirium
22-01-2010, 02:13
Хех, я смотрю я уже не Контрибьютор ) »
XCodeR, видать очень давно не появлялся :)

XCodeR
22-01-2010, 10:18
Delirium,
очень - очень (




© OSzone.net 2001-2012