Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] C# to C++ dll: Маршалинг(?) массива структур (http://forum.oszone.net/showthread.php?t=164134)

XCodeR 20-01-2010 17:57 1325284

C# to C++ dll: Маршалинг(?) массива структур
 
Всем доброе время суток!
Столкнулся с проблемой, которую не могу понять и соотвественно решить.

Имеется 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 1325809

Господа, очень надеюсь на вашу помощь!
Хех, я смотрю я уже не Контрибьютор )

XCodeR 21-01-2010 13:58 1326000

Спасибо всем! вопрос снят.
Нашелся более лаконичный метод.

Небольшой сниппет для будущих поколений:
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 1326591

Цитата:

Цитата XCodeR
Хех, я смотрю я уже не Контрибьютор ) »

XCodeR, видать очень давно не появлялся :)

XCodeR 22-01-2010 10:18 1326739

Delirium,
очень - очень (


Время: 04:43.

Время: 04:43.
© OSzone.net 2001-