Похоже, вы пытаетесь использовать MinGW для компиляции программы, которая использует внешние функции C из сторонней dll. Есть способ экспортировать эти внешние функции в соответствующую библиотеку импорта, которую может использовать gnu ld
компоновщик MinGW, но для этого необходимо создать файл определения .def
. Преимущество этого заключается в том, что после создания правильной библиотеки импорта вам не придется возиться с такими переключателями, как --add-stdcall-alias
или --kill-at
, потому что библиотека импорта будет содержать символы, ожидаемые компилятором и компоновщиком.
Вот примерный план процедуры для этого:
- Вам понадобится вызов инструмента
dlltool.exe
, который должен быть включен в тот же каталог MinGW/bin
, что и компилятор.
- Вам потребуется создать файл определения (*.def), содержащий список всех внешних функций, которые вы хотите импортировать.
- Создайте заглушку файла импорта (*.a), запустив dlltool, передав файл .def, который вы создали в качестве входных данных.
- Передайте только что созданный файл импорта *.a компоновщику при создании проекта, чтобы символы могли быть правильно разрешены.
Вот как выглядит файл определения:
;Run the dlltool like this:
;dlltool -k -d third_party.def -l libthird_party.a
LIBRARY third_party.dll
EXPORTS
dll_function1@0
dll_function2@8
dll_function3@16
; ...
dll_function_n@24
Пара важных моментов, на которые стоит обратить внимание. В разделе EXPORTS
должны быть перечислены экспортированные символы/функции в формате, украшенном именами, как это предусмотрено цепочкой инструментов. В этом случае компилятор MinGW и компоновщик ld ожидают, что __stdcall
функций C будут дополнены символом '@', за которым следует количество байтов в аргументах. Вторая важная вещь, которую следует отметить, это то, что dlltool -k
удалит '@', что делает то же самое, что и опция --kill-at
, которую вы уже видели. Конечным результатом этого является то, что у вас есть библиотека импорта с правильным внутренним украшением имени, поэтому все решается правильно, и это внутреннее имя будет сопоставлено с экспортированным видимым именем, найденным в вашем 3rd сторонняя dll.
И последнее, что нужно упомянуть. На протяжении всего примера мы предполагали, что неукрашенные имена в dll используют __stdcall
, что не обязательно верно. На следующей диаграмме (взято отсюда) показано, как разные компиляторы по-разному украшают __cdecl
и __stdcall
:
MSVC DLL
Call Convention | (dllexport) | DMC DLL | MinGW DLL | BCC DLL
----------------------------------------------------------------------------
__stdcall | _Function@n | _Function@n | Function@n | Function
__cdecl | Function | Function | Function | _Function
Вы должны убедиться, что соглашения о вызовах совпадают должным образом, или рисковать повреждением стека и загадочными сбоями программы.
person
greatwolf
schedule
27.01.2012