LINUX.ORG.RU

Прототипы функций в разделяемых либах для C

 gcc8


0

1

гугль говорит, что это только для C++

Но только что столкнулся с ошибкой сборки проекта (squid), когда при линковке gcc сказал, что неизвестно где ipset_session_init(void *,void*)

Проблема оказалось в том, что в ipset-7.0 изменился прототип для ipset_session_init()

squid C++, ipset - на С. Собиралось все gcc-8.2

Вопрос - а можно ли посмотреть прототипы функций в разделяемой библиотеке ?

★★★★★

Что-то не сходится. Если библиотека сишная, и заголовки обнесены extern «C», то линкер не стал бы жаловаться на несоответсвие сигнатуры. Он про неё сам ничего не знает в случае C.

Gvidon ★★★★
()
Ответ на: комментарий от Gvidon

Не собрал ли ты сишную библиотеку плюсовым компилятором? Если так, то сигнатуры можешь посмотреть обычным nm -C

Gvidon ★★★★
()
Ответ на: комментарий от Gvidon
nm -C /usr/lib64/libipset.so.13 | grep ipset_session_init
0000000000013800 T ipset_session_init

в ipset.cc есть объявление и потом вызов

extern struct ipset_session *ipset_session_init(ipset_outfn_t ipset_outfn );
...
ipset_session = ipset_session_init(printf);
и при линковке (а не компиляции)
ipset.o: In function `ipset_init_lib()':
ipset.cc:(.text+0xcf): undefined reference to `ipset_session_init(int (*)(char const*, ...))'
collect2: error: ld returned 1 exit status
При смене версии ipset изменился прототип. В реальности оно стало «struct ipset_session *ipset_session_init(int (*)(char const*, ...),void *);»

Как линкер об этом узнал ?

vel ★★★★★
() автор топика
Ответ на: комментарий от vel

Компилятор предполагает плюсовую декорацию имён и генерирует зависимость на замангленный символ. Который в сишной библиотеке, естественно, не находится. Занеси объявление внешней функции под extern «C»

Gvidon ★★★★
()
Последнее исправление: Gvidon (всего исправлений: 1)
Ответ на: комментарий от Gvidon

Вопрос в том, как определяется, что в C-шной либе нет функции с определенным прототипом.

Это фича gcc-8 ?

vel ★★★★★
() автор топика
Ответ на: комментарий от vel

В сишной либе нет функции с определённым *именем*. Ты написал объявление

extern struct ipset_session *ipset_session_init(ipset_outfn_t ipset_outfn );
в плюсовом коде. Не указал extern «C». Компилятор воспринимает это как объявление плюсовой функции, которая в бинаре будет иметь имя, задекорированное по правилам декорации имён C++. Такую линкер и ищет.

https://en.wikipedia.org/wiki/Name_mangling

Gvidon ★★★★
()
Последнее исправление: Gvidon (всего исправлений: 1)
Ответ на: комментарий от Gvidon

А при чем тут вообще C++? По сообщению линкера видно что ищется сишное имя, и в библиотеке оно сишное. Просто прототип поменялся.

anonymous
()
Ответ на: комментарий от anonymous

ipset_session_init(int (*)(char const*, ...))

не сишное имя, в этом и проблема. У сишных имён нет информации об аргументах

Gvidon ★★★★
()
Последнее исправление: Gvidon (всего исправлений: 1)
Ответ на: комментарий от Gvidon

nm на объектник раскрыл тайну

Если есть совпадающее описание прототипа с «extern C» и без него, то компилятор не создает mangled прототип.

Спасибо.

vel ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.