Отправка указателя на структуру C # в C ++ DLL - PullRequest
2 голосов
/ 01 марта 2012

У меня есть функция C ++ в DLL, которая берет указатель на структуру JPInfo, которая в функции заполнена данными, полученными с сервера, схема структуры C ++ показана ниже:

typedef struct JP
{
    unsigned char type;
    DWORD value;
} JP;

typedef struct JPInfo
{
    JP jps[3];
    _int16 ConT;
    _int16 CallT;
    unsigned char ret;
    unsigned char count;
    unsigned char JPOffset;
    unsigned char JPPeriod;
} JPInfo;

Функция экспортируется в DLL следующим образом:

__declspec(dllexport) DWORD __stdcall GetJPInfo(JPInfo* jpi, DWORD time);

Функция принимает указатель на структуру JPInfo, я пытался эмулировать эту структуру в C #

[StructLayout(LayoutKind.Sequential, Size = 5), Serializable]
public struct JP
{
    byte type;
    int value;
}

[StructLayout(LayoutKind.Sequential,Size=23),Serializable]
public struct JPInfo
{
    JP[] jps;
    Int16 ConT;
    Int16 CallT;
    byte ret;
    byte count;
    byte JPOffset;
    byte JPPeriod;
}

Я пытаюсь вызвать функцию из C # примерно так:

[DllImport("DLLImp.dll")]
    unsafe public static extern int GetJP(ref JPInfo jpi, int time);
// then in main...
JPInfo jpi = new JPInfo;
GetJackpotValues(ref jpi, 4000);

Я получаю необработанное исключение типа "System.ExecutionEngineException". В моей структуре JPInfo не может быть массива JP-структур фиксированного размера, поэтому я не знаю, как к этому подойти.

Спасибо.

Ответы [ 2 ]

4 голосов
/ 01 марта 2012

Вы пытались удалить атрибуты размера на своих структурах? Мне не нужно было указывать размер при выполнении чего-то подобного. Для ваших свойств массива, попробуйте присвоить их следующим образом:

[StructLayout(LayoutKind.Sequential)]
public struct JPInfo
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    JP[] jps;
    Int16 ConT;
    Int16 CallT;
    byte ret;
    byte count;
    byte JPOffset;
    byte JPPeriod;
}
2 голосов
/ 01 марта 2012

Предполагая, что структуры C ++ упакованы, ваши структуры C # должны выглядеть следующим образом:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct JP
{
    byte type;
    uint value;
}

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct JPInfo
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
    JP[] jps;
    Int16 ConT;
    Int16 CallT;
    byte ret;
    byte count;
    byte JPOffset;
    byte JPPeriod;
}

С другой стороны, если они не упакованы, удалите параметр Pack в атрибут StructLayout. Вы должны искать оператор #pragma pack в заголовочном файле C ++, чтобы понять, упакованы ли структуры C ++.

Я предполагаю, что структуры C ++ упакованы, потому что вы сказали, что они отображаются на данные, полученные с сервера.

Ваш импорт должен быть таким:

[DllImport("DLLImp.dll")]
public static extern uint GetJP(ref JPInfo jpi, uint time);

A DWORD переводится в uint вместо int, и здесь нет необходимости в небезопасном коде.

...