| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Классы в библиотеках |
| Автор: EvgeniyK77 15.8.2012, 08:01 | ||||||||
| Подскажите, пожалуйста, как корректно разместить класс в статической библиотеке (.a)? Поясню суть. Есть некоторый класс, который я скомпилировал в Linux с помощью mingw. Полученную библиотеку и заголовочный файл дал другому человеку, который её использовал в своей программе. Всё было здорово. Всё чудно линковалось и работало... До поры до времени. После очередного обновления mingw (у него) программа стала падать в одном из моих методов. При этом линковщик не ругался. После пересборки моей библиотеки на его машине падения прекратились. Стал разбираться. Оказалось, что mingw вдруг решил для методов поменять порядок аргументов (this поместил в другое место)! Я, конечно, понимаю, что классы в библиотеках - это не очень хорошо, т.к. разные компиляторы по-разному генерят имена для методов, и библиотека, собранная одним компилятором, может не подлинковаться другим. Но компилятор ведь один! Да и линковка прошла успешно... Быть может, есть какие-то стандартные способы, типа extern "C"? Если интересно, вот тест (библ. собрана на Fedora 14, а программа - на Fedora 17):
Программы выводит:
|
| Автор: Cheloveck 15.8.2012, 10:11 |
this передаётся в регистре ECX, это конвенция http://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D0%B3%D0%BB%D0%B0%D1%88%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B2%D1%8B%D0%B7%D0%BE%D0%B2%D0%B0#thiscalll и никаких вольностей компилятор тут позволять себе не должен. Порядок аргументов тоже определён thiscall. Проблема где-то в другом месте. |
| Автор: korian 15.8.2012, 11:21 |
Это всего лишь соглашение, а не стандарт. И никто его поддерживать не обязан. Да и что делать на системах, в которых регистра ECX изначально не было? http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/281008-gcc-thiscall-calling-convention-linux-win32-mingw.html EvgeniyK77, Я точно не знаю, но поидее надо или перекомпиливать все одним компилятором или использовать только cdecl С-функции, т.е. никакого C++ наверху торчать не должно. |
| Автор: EvgeniyK77 17.8.2012, 09:10 |
| Спасибо! Стал разбираться с модификаторами и узнал, что в mingw 4.7 умолчальный модификатор методов изменился на __thiscall. В 4.5 такого вообще нет. Если у метода явно поставить __fastcall, __stdcall или __cdecl, то всё работает! Какой из этих модификаторов предпочтительнее? |
| Автор: leniviy 17.8.2012, 09:17 | ||
не мог бы ты приаттачить 2 версии тестовой либы? Одну собранную на старом MinGW, другую - на новом. Естественно, с -g -O0. По идее, у методов __cdecl и __thiscall должна быть разная сигнатура. Visual C++:
@@QAAXXZ vs @@QAEXXZ То есть, программа не должна была компилироваться. |
| Автор: EvgeniyK77 17.8.2012, 10:29 |
| Сделано! |
| Автор: leniviy 17.8.2012, 10:45 | ||
| спасибо. Похоже, что в mingw gcc сигнатура одинаковая. Идеального нет. Я бы использовал __thiscall, так как он быстрее:
А на старом компиляторе пускай не собирается. Кто умеет ставить MinGW, сможет поставить и новый MinGW |
| Автор: Randajad 17.8.2012, 13:04 |
| Кто сказал, что классы в библиотеках - плохая идея? Не говорите таких глупостей. GCC версии < 4.7 передает this через стэк. GCC версии >= 4.7 передает this через ecx на x86 платформах. Это сделано для обеспечения совместимости с MSVC либами. Другого не дано. Не нужно указывать никаких extern/__thiscall в статических либах. Зачем? Просто используйте оба компилятор или выше 4.6, или равный и ниже ему. Добавлено через 4 минуты и 9 секунд To leniviy: Вопрос насчет быстроты __thiscall спорный. Может, тогда fastcall еще быстрее? Однако, его никто не использует. |
| Автор: Randajad 17.8.2012, 14:42 |
| Это все хорошо, но этот шаг сделан именно ради улучшения совместимости с MSVC. Такие "валы" видны сразу же при первом запуске. Виноват человек и пихать везде MYCALL - не решение проблемы. Почему между двумя? Fastcall поддерживает классы тоже. |
| Автор: EvgeniyK77 20.8.2012, 07:29 | ||
На различия компиляторов я не думал, т.к. считал, что либа, в случае чего, просто не подлинкуется. |