Получение System.ExecutionEngineException Ошибка вызова функции C, которая передает массив структур в C # - PullRequest
2 голосов
/ 10 января 2012

Я создаю оболочку COM, написанную на C #, вокруг C dll и получаю сообщение об ошибке, когда я вызываю одну конкретную функцию, которая принимает ссылку на предварительно инициализированный массив структур.

Ошибка: «Необработанное исключение типа 'System.ExecutionEngineException произошло в sXEposCOM.dll"

Функция C имеет следующую подпись:

UINT16 sXGetSupportedSchemes( SXEposScheme_t *pSchemes );

И структура SXEposScheme_t в Cll dll объявлена ​​как:

typedef struct _SXEposScheme_t
{
BYTE    schemeID[SX_EPOS_SID_LENGTH];
char    schemeName[SX_EPOS_MAX_SCHEME_NAME_LENGTH];
} SXEposScheme_t;

В моей оболочке C # (sXEposCOM) у меня есть следующее:

private const int SX_EPOS_SID_LENGTH    = 2;
private const int SX_EPOS_MAX_NUM_SCHEMES = 10;

[DllImport("SXEposDll.dll")]
private static extern UInt16 sXGetSupportedSchemes(ref SXEposScheme_t [] pSchemes);

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SXEposScheme_t
{
    [MarshalAs(
    UnmanagedType.ByValArray,
    SizeConst = SX_EPOS_SID_LENGTH)]
    public byte[] schemeID;
    [MarshalAs(
    UnmanagedType.ByValArray,
    SizeConst = SX_EPOS_MAX_SCHEME_NAME_LENGTH)]
public char [] schemeName;
}

public int GetSupportedSchemes()
{
    uint result = 0;
    uint schemeCnt = 0;
    GetNumSchemes(ref schemeCnt); //This call to the C dll succeeds and returns 2 to   schemeCnt

    SquidEposScheme_t[] schemes = new SXEposScheme_t[schemeCnt];    
    result = sXGetSupportedSchemes(ref schemes); //Errors on this line with An unhandled exception of type 'System.ExecutionEngineException occurred in sXEposCOM.dll

...
...
return result;
}       

Может кто-нибудь сказать мне, почему я получаюэта ошибка?

1 Ответ

1 голос
/ 10 января 2012

Это исключение срабатывает, когда собственный код повреждает кучу мусора.Здесь много возможностей, ваши объявления на C # выглядят неправильно.Массив уже передан как указатель, добавление ref к аргументу делает его указателем на указатель.Возможное исправление:

[DllImport("SXEposDll.dll")]
private static extern UInt16 sXGetSupportedSchemes([In,Out] SXEposScheme_t [] pSchemes);

Pack = 1 очень редко подходит, используйте ByValTStr для маршалинга строки.Возможное исправление:

[StructLayout(LayoutKind.Sequential)]
public struct SXEposScheme_t
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = SX_EPOS_SID_LENGTH)]
    public byte[] schemeID;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = SX_EPOS_MAX_SCHEME_NAME_LENGTH)]
    public string schemeName;
}
...