mingw32 g++ и stdcall @suffix

Я объявил некоторые функции C++, прототипированные следующим образом:

extern "C" void __stdcall function();

У меня тоже какая-то сторонняя dll с экспортированными function() - вообще без украшений имени. Я не могу собрать свой exe или dll из-за undefined reference to function@... из-за @-суффикса MinGW stdcall. Как я могу получить объектный файл без @... просто имен функций?


person j.l.    schedule 09.11.2011    source источник


Ответы (2)


Похоже, вы пытаетесь использовать MinGW для компиляции программы, которая использует внешние функции C из сторонней dll. Есть способ экспортировать эти внешние функции в соответствующую библиотеку импорта, которую может использовать gnu ld компоновщик MinGW, но для этого необходимо создать файл определения .def. Преимущество этого заключается в том, что после создания правильной библиотеки импорта вам не придется возиться с такими переключателями, как --add-stdcall-alias или --kill-at, потому что библиотека импорта будет содержать символы, ожидаемые компилятором и компоновщиком.

Вот примерный план процедуры для этого:

  1. Вам понадобится вызов инструмента dlltool.exe, который должен быть включен в тот же каталог MinGW/bin, что и компилятор.
  2. Вам потребуется создать файл определения (*.def), содержащий список всех внешних функций, которые вы хотите импортировать.
  3. Создайте заглушку файла импорта (*.a), запустив dlltool, передав файл .def, который вы создали в качестве входных данных.
  4. Передайте только что созданный файл импорта *.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

man ld дает вам опцию --enable-stdcall-fixup для компоновки не-@-декорированных библиотек. Я не уверен, что ведущие символы подчеркивания будут проблемой, вам придется попробовать.

Если вы хотите создавать объектные файлы или библиотеки DLL с помощью mingw и хотите экспортировать имена без «@», --kill-at — ваш друг.

person thiton    schedule 09.11.2011
comment
Нет, это не работает. Кроме того, если я правильно помню, исправления stdcall выполняются автоматически, если это применимо, и нужно только использовать --disable. Я ищу удаление @ - person j.l.; 09.11.2011
comment
Если вы хотите сделать ссылку против @, для этого и нужны исправления stdcall. Или вы хотите создать DLL с помощью mingw и не экспортировать символы с помощью @? - person thiton; 09.11.2011
comment
Как я уже говорил ранее, у меня есть какая-то сторонняя dll с экспортируемой функцией (и эту функцию, вероятно, нужно вызывать через stdcall, потому что она используется в каком-то старом образце VisualBasic) и вообще никаких украшений, и я написал внешнюю функцию C++. Что мне действительно нужно, так это объектный файл без @-суффикса. Таким образом, я могу протестировать его дважды: 1) выполнить через С++, 2) протестировать промежуточное звено С++ в VisualBasic, чтобы устранить некоторые возможные проблемы, связанные с указателями и т. д. Но ничего не работает, я пробовал параметры g++, objcopy,... - person j.l.; 09.11.2011
comment
поэтому одна из возможностей - --add-stdcall-alias, таким образом можно получить объект без (и с) @-суффиксом. Я уже пробовал это, но это работает только сейчас (может быть, опции компоновщика идут последними?) - person j.l.; 09.11.2011