Ошибка BadImageFormatException при использовании функции C ++ .dll для C #? - PullRequest
1 голос
/ 18 мая 2011

У меня проблемы с использованием P / Invoke для C #. Вот функция (написанная на C ++), которую я пытаюсь вызвать из .dll:

string
BeatTracker::getName() const
{
    return "Tempo and Beat Tracker";
}

А вот мой код для попытки вызова этой функции:

[DllImport("qm-vamp-plugins.dll",EntryPoint="BeatTracker")]
public static extern string getName();

public QMTempo()
{
   Console.WriteLine(getName());
}

Что, похоже, не так? Я получаю BadImageFormatException. И как я могу узнать, что не так в будущих ссылках, кроме смутных имен, которые мне дает IDE? Кстати, я использую Visual Studio 2008.

Также я использую (но не уверен, правильно ли) EntryPoint, чтобы сообщить ему, что я использую функцию getName из класса BeatTracker (потому что есть также функции getName для других классов, которые включены в один .dll). файл)

Спасибо!

Ответы [ 2 ]

8 голосов
/ 18 мая 2011

Это исключение может быть вызвано несоответствием между используемой архитектурой .NET runtime proc и импортированной библиотекой dll.

Точнее:

Вы используете 64-битную Windows? Среда выполнения по умолчанию будет работать в 64-битном режиме. Если ваша библиотека C ++ была скомпилирована для 32-битной системы, вы получите BadFormatException при загрузке библиотеки. То же самое происходит, если ваше .NET-приложение работает на 32-битной версии, а ваша библиотека C ++ была скомпилирована для x64.

Если вы можете перекомпилировать библиотеку, сделайте это. В противном случае вы можете заставить среду выполнения .NET использовать указанную архитектуру при компиляции, но это не позволит ей работать на другой архитектуре. Это ваш выбор;) При кодировании на .NET или Java мы склонны забывать, что на самом деле происходит под капотом.

3 голосов
/ 18 мая 2011
[DllImport("qm-vamp-plugins.dll",EntryPoint="BeatTracker")]

EntryPoint должно быть getName(), а не BeatTracker, что является классом!

Но даже тогда вы не можете вызвать это, потому что getName() является функцией-членом, которую нельзя вызвать без экземпляра.

Поэтому я бы предложил определить свободные функции в DLL и экспортировать их. Вы можете использовать класс внутри, в DLL. Вы можете работать с ручкой классов.

Пример,

Код DLL:

typedef BeatTracker* PBeatTracker;
typedef PBeatTracker HBeatTracker; 

//exported functions
HBeatTracker CreateBeatTracker()
{
      return new BeatTracker();
}
void DeleteBeatTracker(HBeatTracker  handle)
{
     delete handle;
}
string getName(HBeatTracker handle)
{
    return handle->getName();
}

C # Код:

[DllImport("qm-vamp-plugins.dll",EntryPoint="CreateBeatTracker")]
public static extern IntPtr CreateBeatTracker();

[DllImport("qm-vamp-plugins.dll",EntryPoint="DeleteBeatTracker")]
public static extern void DeleteBeatTracker(IntPtr);

[DllImport("qm-vamp-plugins.dll",EntryPoint="getName")]
public static extern string getName(IntPtr);

public QMTempo()
{
   IntPtr handle = CreateBeatTracker();
   Console.WriteLine(getName(handle));
   DeleteBeatTracker(handle);
}
...