Похоже, вы пытаетесь использовать MinGW для компиляции программы, которая использует внешние функции C из сторонней библиотеки dll.Есть способ экспортировать эти внешние функции в правильную библиотеку импорта, которую может использовать компоновщик MinGW gnu ld
, но это включает создание файла определения .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
, которую вы уже видели.Конечным результатом этого является то, что у вас есть библиотека импорта с правильным внутренним украшением имени, поэтому все разрешается правильно, и , это внутреннее имя будет сопоставляться с экспортированным видимым именем, найденным в вашем 3 rd party 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
Вы должны убедиться, что соглашения о вызовах соответствуютили рискуете испортить стек и загадочные сбои программы.