У меня есть функция в libA.so
, которая используется в libB.so
,
И функция в libB.so
, которая используется в libA.so
!
Поэтому я не могу скомпилировать ни одну из этих библиотек.
Как я могу скомпилировать эти две библиотеки?
Следует ли мне использовать третью библиотеку и перенести зависимости в эту библиотеку?
Я использовал qt и C++
Обновлено: в компиляции libA.so получить ошибку не удается найти libB.so и в libB.so получить ошибку не удается найти libA.so
«Итак, я определенно не могу скомпилировать ни одну из этих библиотек». Это просто неправда. Попробуйте, и если вы получите сообщение об ошибке, задайте вопрос об этой конкретной ошибке.
Так как же это сделать?
@ n.m. в компиляции libA.so получить ошибку не удается найти libB.so и в libB.so получить ошибку не удается найти libA.so
Ошибка от компоновщика, а не от компилятора. Вы делаете нет, чтобы сообщить компоновщику, что libA.so
нужен libB.so
. (Общие библиотеки не работают как библиотеки DLL). Просто удалите -lB
из командной строки. Если хотите, вы можете связать libA.so
без -lB
, затем собрать libB.so
и затем повторно связать libA.so
с -lB
, но это строго необязательно.
Пожалуйста, редактировать вопрос и добавьте свой комментарий «в compile libA.so получить ошибку не могу найти libB.so и в libB.so получить ошибку не могу найти libA.so» к самому вопросу. Существенная информация должна идти к вопросу, а не к комментариям.
@ n.m. если я удалю -lB, компилятор получит ошибку, что функция не найдена в классе libB, который я использовал в libA
Не может быть. Компилятор и компоновщик - это разные вещи. Компилятор ничего не знает о флаге -lB
. Если вы получаете ошибку компилятора, вы никогда не дойдете до стадии компоновщика, и -lB
не вступит в игру. Вам следовало удалить только -lB
, а не все флаги -I
. Пожалуйста, редактировать вопрос и добавьте минимальный воспроизводимый пример с вашими фактическими командами компиляции и фактическими сообщениями об ошибках.
Это кажется немного проблематичным для повторного использования в будущем. Возможно, вы захотите либо разделить свои функции по-разному между этими библиотеками, либо создать третью, которая будет содержать все «инструментальные» функции, чтобы LibA
и libB
функционировали друг без друга.
БОЛЬШОЙ ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ Делайте это только в случае крайней необходимости. Предпочтительный способ - реорганизовать структуру вашего проекта так, чтобы она не содержала циклов зависимостей.
При создании разделяемой библиотеки компоновщику, как правило, не нужно знать о других разделяемых библиотеках. Их можно использовать в командной строке, но это необязательно. Пример:
// libA.cpp
extern void funcB();
void funcA() {
funcB();
}
Скомпилируйте и свяжите:
g++ -fPIC -c libA.cpp
g++ -shared -o libA.so libA.o
Предполагается, что funcB
находится в libB.so
, но мы не сообщаем компоновщику, где его найти. Символ просто оставлен неопределенным в libA.so
и будет (надеюсь) разрешен в время загрузки.
// libB.cpp
extern void funcA();
void funcB() {
funcA();
}
Скомпилируйте и скомпилируйте, теперь явно используя libA.so (игнорируйте бесконечную рекурсию, это просто пример):
g++ -fPIC -c libB.cpp
g++ -shared -o libB.so libB.o -L/where/libA/is -lA
Теперь исполняемый файл должен загрузить libB.so
перед загрузкой libA.so
, иначе libA.so
не может быть загружен. Это легко сделать (просто свяжите исполняемый файл только с libB.so
, а не с libA.so
), но иногда это может быть неудобно. Таким образом, можно повторно связать libA.so
после, построив libB.so
:
g++ -shared -o libA.so libA.o -L /where/libB/is -lB
Теперь можно связать исполняемый файл с libA или libB, а другой будет подхвачен автоматически.
Наконец решаю.
Как @ n.m. сказал, что нам не нужно связывать libA.so и libB.so во время компиляции, поэтому я удаляю -lA
и -lB
при их сборке, и у меня не было никаких ошибок. И в приложении, которое хочет использовать libA.so или libB.so, я связал их с -lA
или -lB
. Так что это работает правильно.
I have a function in libA.so that is used in libB.so, And a function in libB.so that is used in libA.so!
Это неправильный дизайн. библиотека не может даже косвенно зависеть от самого себя. Такая замкнутость является признаком чего-то очень неправильного, и вы неправильно понимаете, что такое программная библиотека (это больше, чем случайный набор функций или объектных файлов; это должен быть каким-то образом «программный модуль», и это связано с к модульное программирование и часто определяет и реализует полностью как набор связанные сабстрактные типы данных).
Итак, выбросьте как libA.so
, так и libB.so
. И сделать ОдинlibAB.so
, содержащий весь код, который вы поместили в общие объекты libA.so
и libB.so
(а не в подлинные библиотеки).
ответ с н.м. дает технический способ решения вашей проблемы, но в глубине души ваш дизайн неправильный, и вы злоупотребляете библиотеками (и вы не можете называть свой libA
или libB
библиотекой, даже если вы создали их как некоторый общий объект в ELF).
Вы также можете разработать свой код, добавив некоторое косвенное обращение с обратные вызовы или закрытие или указатели на функции, содержащимся в какой-либо переменной или данных (и предоставить способ установить эти обратные вызовы или инициализировать замыкания или указатели функций в время выполнения). Поскольку вы используете Qt, подумайте также о том, чтобы правильно определить ваш новый Сигналы и слоты Qt (они основаны на некотором механизме обратного вызова).
Прочтите статью Программная библиотека HowTo и Дреппера Как писать общие библиотеки, чтобы узнать больше.
Помещение общих функций в отдельную библиотеку, которую можно использовать повторно, - безусловно, хорошая идея.