PInvoke Array Marshalling Failure

0

У меня есть следующая функция C++, экспортированная в DLL:

extern "C" __declspec(dllexport) bool GetResolutionArray(int32_t adapterIndex, int32_t outputIndex, uint32_t arrayLength, Resolution outResolutionArr[]) {
        memcpy_s(
        outResolutionArr, 
        sizeof(Resolution) * arrayLength,
        RENDER_COMPONENT.GetResolutionArray(adapterIndex, outputIndex),
        RENDER_COMPONENT.GetOutput(adapterIndex, outputIndex).NumResolutions * sizeof(Resolution)
        );
    return true;
}

И, соответствующая декларация функции extern в С#:

[DllImport(InteropUtils.RUNTIME_DLL, EntryPoint = "GetResolutionArray", CallingConvention = CallingConvention.Cdecl)]
internal static extern bool _GetResolutionArray(int adapterIndex, int outputIndex, uint resolutionArrayLength, [MarshalAs(UnmanagedType.LPArray), In, Out] ref Resolution[] resolutions);

Однако, когда я пытаюсь использовать эту функцию, как показано ниже, программа выходит из строя с помощью FatalExecutionEngineError (указывая, что я что-то исказил где-то, я думаю) (код ошибки 0xc0000005, т.е. нарушение прав доступа):

Resolution[] resolutions = new Resolution[outOutputDesc.NumResolutions];
if (!_GetResolutionArray(outAdapterDesc.AdapterIndex, outOutputDesc.OutputIndex, (uint) resolutions.Length, ref resolutions)) {
    EnginePipeline.TerminateWithError("Internal engine call failed: _GetResolutionArray");
}

Я сильно подозреваю, что мой вызов memcpy_s вызывает нарушение прав доступа, но я не могу понять, как и почему, и поэтому я считаю, что, возможно, маршаллинг что-то происходит не так.

Спасибо.

  • 0
    Попробуйте выполнить маршалинг только OUT, а не in и out для вашего возвращаемого параметра. Кроме того, что такое EnginePipeline.TerminateWithError ()? Я бы смягчил это и обязательно добавил полное сообщение об ошибке в вопрос здесь.
  • 0
    @ebyrob попробовал, без эффекта.
Показать ещё 8 комментариев
Теги:
memcpy
pinvoke

1 ответ

0
Лучший ответ

Параметр массива объявлен неверно. AС# array уже является ссылкой, поэтому вам не нужен ref. Объявите это следующим образом:

[DllImport(InteropUtils.RUNTIME_DLL, EntryPoint = "GetResolutionArray", 
    CallingConvention = CallingConvention.Cdecl)]
internal static extern bool _GetResolutionArray(int adapterIndex, 
    int outputIndex, uint resolutionArrayLength, Resolution[] resolutions);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню