P / Invoke бросить System.ExecutionEngineException - PullRequest
1 голос
/ 02 декабря 2009

У меня есть неуправляемая DLL с закрытым исходным кодом, написанная на C ++, которую я хотел использовать в решении C #, поэтому я создал управляемую оболочку DLL, которая использует P / Invoke для вызова функции DLL с закрытым исходным кодом. Это очень хорошо работает без функции param и переменных типа int. Однако я получаю System.ExecutionEngineException при запуске более сложной функции, которая принимает массив struct в качестве параметра, который содержит массив char для строк. Вот что у меня было:

[StructLayout(LayoutKind.Sequential)]
public struct Target
{
    public int targetID;

    public string Label;
}

[DllImport("tyrfde.dll", EntryPoint = "tyrfdeGetTarget")]
public static extern int GetTarget(ref Target[] targets);

Ниже приведена информация из заголовочного файла DLL:

#define TARGET_LBL_SIZE   (256l)

typedef struct _tyrfdeTarget
{
    TInt32 TargetID;                   // integer signed 32bits
    TCharA Label[TARGET_LBL_SIZE];     // caracter
} tyrfdeTarget;

TInt32 __stdcall tyrfdeGetTargets(tyrfdeTarget* pTargets);

Не совсем уверен, почему размер массива указан как long, но в любом случае SizeConst принимает только int. После некоторого поиска вот что я пытался исправить.

[StructLayout(LayoutKind.Sequential, Size = 260), Serializable]
public struct Target
{
    public int targetID;

    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string Label;
}

[DllImport("tyrfde.dll", EntryPoint = "tyrfdeGetTargets")]
public static extern int GetTarget(ref Target[] targets);

Но у меня все еще есть проблема. Я читал, что это исключение можно выбросить, если функции очищают часть памяти, используемой CLR. К сожалению, я не могу это проверить. Есть ли в моем коде что-то явно неправильное и может вызвать проблему?

Ответы [ 2 ]

2 голосов
/ 02 декабря 2009

Хм, я думаю, что ваша проблема с параметром ref Target[] targets. AFAIR это ссылка на ссылку, которая, вероятно, не то, что вы на самом деле хотите.

Я бы попробовал это:

[DllImport("tyrfde.dll", EntryPoint = "tyrfdeGetTargets")]
public static extern int GetTarget([Out, MarshalAs(UnmanagedType.LPArray)] Target[] targets);

Может быть эта статья поможет вам найти правильное объявление.

Обратите внимание, что размер массива здесь неясен, обычно в таких случаях есть также параметр ref int length, на который можно ссылаться в атрибуте MarshalAs через свойство SizeParameterIndex.

0 голосов
/ 02 декабря 2009

1) Вы уверены, что TCharA является 16-битным? В противном случае, я думаю, вам также следует указать, какой CharSet использовать.

2) Написание таких оболочек намного проще в C ++ / CLI.

...