Свяжите две библиотеки друг с другом

У меня есть функция в libA.so, которая используется в libB.so, И функция в libB.so, которая используется в libA.so! Поэтому я не могу скомпилировать ни одну из этих библиотек. Как я могу скомпилировать эти две библиотеки? Следует ли мне использовать третью библиотеку и перенести зависимости в эту библиотеку? Я использовал qt и C++

Обновлено: в компиляции libA.so получить ошибку не удается найти libB.so и в libB.so получить ошибку не удается найти libA.so

Помещение общих функций в отдельную библиотеку, которую можно использовать повторно, - безусловно, хорошая идея.

Some programmer dude 10.09.2018 09:44

«Итак, я определенно не могу скомпилировать ни одну из этих библиотек». Это просто неправда. Попробуйте, и если вы получите сообщение об ошибке, задайте вопрос об этой конкретной ошибке.

n. 1.8e9-where's-my-share m. 10.09.2018 10:00

Так как же это сделать?

ebigood 10.09.2018 10:01

@ n.m. в компиляции libA.so получить ошибку не удается найти libB.so и в libB.so получить ошибку не удается найти libA.so

ebigood 10.09.2018 10:03

Ошибка от компоновщика, а не от компилятора. Вы делаете нет, чтобы сообщить компоновщику, что libA.so нужен libB.so. (Общие библиотеки не работают как библиотеки DLL). Просто удалите -lB из командной строки. Если хотите, вы можете связать libA.so без -lB, затем собрать libB.so и затем повторно связать libA.so с -lB, но это строго необязательно.

n. 1.8e9-where's-my-share m. 10.09.2018 10:05

Пожалуйста, редактировать вопрос и добавьте свой комментарий «в compile libA.so получить ошибку не могу найти libB.so и в libB.so получить ошибку не могу найти libA.so» к самому вопросу. Существенная информация должна идти к вопросу, а не к комментариям.

n. 1.8e9-where's-my-share m. 10.09.2018 10:10

@ n.m. если я удалю -lB, компилятор получит ошибку, что функция не найдена в классе libB, который я использовал в libA

ebigood 10.09.2018 10:11

Не может быть. Компилятор и компоновщик - это разные вещи. Компилятор ничего не знает о флаге -lB. Если вы получаете ошибку компилятора, вы никогда не дойдете до стадии компоновщика, и -lB не вступит в игру. Вам следовало удалить только -lB, а не все флаги -I. Пожалуйста, редактировать вопрос и добавьте минимальный воспроизводимый пример с вашими фактическими командами компиляции и фактическими сообщениями об ошибках.

n. 1.8e9-where's-my-share m. 10.09.2018 10:15
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
824
4

Ответы 4

Это кажется немного проблематичным для повторного использования в будущем. Возможно, вы захотите либо разделить свои функции по-разному между этими библиотеками, либо создать третью, которая будет содержать все «инструментальные» функции, чтобы 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 и Дреппера Как писать общие библиотеки, чтобы узнать больше.

Другие вопросы по теме