Почему возникает исключение AccessViolationException при вызове импортированной функции C ++ из кода C#? - PullRequest
0 голосов
/ 16 марта 2020

Я читал много веток о topi c, но пока не смог найти решение своей проблемы.

Из своего кода C# я пытаюсь вызвать функцию C ++ используя DllImport. К сожалению, у меня нет кода C ++, но файл заголовка дает информацию о функции:

ABCD Initialize
(
  IN FLOAT a  
  , IN DWORD b  
);  

ABCD также определен в файле заголовка:

#define EFGH extern "C"
...
#define ABCD EFGH __declspec(dllexport) HRESULT WINAPI

In C# код, я пытаюсь вызвать функцию Initialize следующим образом:

[DllImport("path.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern UInt32 Initialize([In] float a, [In] UInt32 b);
...
Initialize(50.0f, 0);

Согласно этому сайту нет необходимости в маршаллинге для типа данных float, и вместо этого DWORD Я могу использовать UInt32. Для типа возврата HRESULT WINAPI я использую тип данных UInt32, и в моем понимании нет необходимости в сортировке? (я также пытался использовать другие типы данных для параметров и возвращаемого значения, но всегда получал одно и то же исключение)

Для атрибута DllImport много возможностей для CharSet и CallingConventions были проверены, но у меня не было успеха. При объявлении функции я также попробовал оба варианта, с и без атрибута [In] для параметров.

При вызове функции выдается исключение:

System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

Am Я что-то здесь упустил? Какие могут быть следующие шаги для успешного вызова функции?

Спасибо.


Вот полный код C#. Как я уже сказал, у меня нет кода, который использовался для создания DLL-файла. Также мне не разрешено делиться dll.

using System;
using System.Runtime.InteropServices;

namespace MyNamespace
{
  class Program
  {
    [DllImport("path.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern UInt32 Initialize([In] float a, [In] UInt32 b);

    static void Main(string[] args)
    {
      Initialize(50.0f, 0); // <- throws System.AccessViolationException
      Console.ReadLine();
    }
  }
}

1 Ответ

0 голосов
/ 17 марта 2020

Наконец, я смог определить проблему.

Для проверки типов данных параметров и возвращаемого значения я использовал декомпилятор Снеговик на dll. Похоже, DLL определяет только интерфейсы, и что реализации находятся в другом файле DLL, который разработчик забыл отправить в первую очередь.

После того, как второй файл .dll сохраняется в папке времени выполнения моей программы, вызов функции работает. Я также хочу упомянуть, что вызов работает с атрибутами атрибута [In] и без них.

Хотя я не знаю точную причину выданного исключения AccessViolationException: Attempted to read or write protected memory... (я думаю, что другое исключение могло бы быть лучше здесь) Я рад, что проблема может быть решена.

Благодарю Бена Фойгта и Дэвида Хеффернана за их комментарии!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...