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

У меня есть функция в 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
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 и Дреппера Как писать общие библиотеки, чтобы узнать больше.

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