LINUX.ORG.RU

Linux C++ Как обернуть свои классы, использующие стороние библиотеки, в библиотеку?


0

2

Добрый день! У меня есть следующее:

A.h
#include <curl/curl.h>
class A
{
public:
  void Method();
};
A.cpp
#include "A.h"
void A::Method() {}
Мне нужно обернуть этот класс(набор классов), использующий библиотеку curl в библиотеку. (Статическую и динамическую), чтобы клиент мог использовать метод Method. То есть уметь выполнить у себя нечто типа (при этом curl на клиенте не установлен):
#include "A.h"
A a;
a.Method()
Не подскажете, как правильно собрать статическую и динамическую биюлиотеку в моем случае и скомпилировать клиентский код библиотекой для проверки?



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

Ну так замени

target_link_libraries(foo -lcurl)
на
target_link_libraries(foo "-Wl,--whole-archive" curl "-Wl,--no-whole-archive")
Скомпиляй только библиотечку. В секцию установки добавь эту библиотечку. А еще лучше оформи библиотеку отдельно, оставив только секцию установки.

Тогда по идее все сработает. Для бинаря будешь писать только

project(hello_world)
set(SOURCE_EXE main.cpp) 
target_link_libraries(test foo)
add_executable(test ${SOURCE_EXE})
(лучше добавить поиск библиотеки foo, чтобы cmake матерился, если ее нет).

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

Скомпиляй только библиотечку. В секцию установки добавь эту библиотечку. А еще лучше оформи библиотеку отдельно, оставив только секцию установки. То есть?

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

C cmake было бы здорово, но может кто-то подскажет как мне подключить собранную мной библиотеку просто к проекту?

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

За 5 часов можно было бы прочитать руководство cmake

anonymous
()

похоже это первый кандидат в мой игнор лист.

Masha слово man тебе знакомо?

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

Я пробовала компилить отдельно код клиента с полученной библиотекой libfoo.a

g++ -g *.cpp -o test -O2 -lfoo -lrt
Не удается найти h-файл fatal error: A.h: No such file or directory compilation terminated.

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

Ответ на: комментарий от Masha 02.10.2013 18:22:18 Скомпиляй только библиотечку. В секцию установки добавь эту библиотечку. А еще лучше оформи библиотеку отдельно, оставив только секцию установки. То есть?

Masha (02.10.2013 18:28:26)

Тихо сам с собою я веду беседу...

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

Только ССЗБ вручную пишет Makefile!

разок полезно написать...

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

сиськи уже были?

похоже не будет. Расходимся поцаны...

ЗЫЖ по теме всё сказали уже...

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

Самое простое - при линковке указать напрямую библиотеку:

$gcc -o mega_app mega_app.cpp /home/masha/lib/libcurl/libcurl.a
DELIRIUM ☆☆☆☆☆
()

Хмм, а никого не смущает, что в A.h содержится

#include <curl/curl.h>

и устанавливать curl для использования библиотеки все равно придется.

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

abalakin ★★
()

динамическую g++ -shared A.cpp -lcurl -o liba.so

статическую g++ -c A.cpp -o a.o && ar rcs liba.a a.o

клиент g++ client.cpp -la -lcurl -o client

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

и устанавливать curl для использования библиотеки все равно придется.

тогда так

1. скомпилять curl статиком

./configure --enable-static --prefix $HOME/build/curl make make install

я собираю с такими флагами --enable-static --disable-ldap --disable-ldaps --without-ssl --without-zlib --without-gnutls --without-nss --without-libssh2 --without-librtmp --without-libidn --disable-nls --disable-rtsp --disable-verbose

(так у курла не будет лишних депендов, но если они нужны — придется и их аналогичным образом собирать и подключать, см. ниже)

2. собрать свою либу: g++ -shared A.cpp $HOME/build/curl/lib/libcurl.a -o liba.so

если твоя либа статическая — то просто при сборке клиента подкидывай ему и свою либу, и curl.

т.е.

g++ client.cpp liba.a libcurl.a -o client

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

Почему в треде ни одного комментария про отсутствие стандартного ABI в C++?

это будет следующий вопрос ТСа :D

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

извини, ответил нечаянно не тебе, а abalakin, пост Linux C++ Как обернуть свои классы, использующие стороние библиотеки, в библиотеку? (комментарий) тебе адресован :D

и насчет cmake ничего не подскажу, я его ненавижу лютой ненавистью.

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

Дараѓой! Бабе дали задание — прокормить целую воинскую часть! Вот и выполняет. Ну, а там само собой разумеется, что помимо МСВС 2008-го года выпуска есть еще и более древние варианты…

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

А вообще, это же извращение: линковать curl куда-то статически! Ну покажи мне машину, где нет libcurl! Это что — МСВС начала этого тысячелетия?

во-первых, таки есть машины где нет libcurl. например венда и андроид. насчет линукса не уверен. в базовую систему он не входит обычно, вроде.

во-вторых, никогда не знаешь какая версия курла окажется у юзера. может получиться так, что дремучая. с неисправленными багами, которые влияют на твое приложение. поэтому я когда бинари распространяю - линкую статиком.

в-третьих, если линкуешь динамически — придется, как Зенитару, собирать свой проект на дремучей центоси, т.к. только там есть достаточно древняя версия курла, чтобы твоя программа запустилась на других компах (где нет последней версии).

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

Не удается найти h-файл fatal error: A.h: No such file or directory compilation terminated.

тебе придется A.h со своей библиотекой раздавать в любом случае. а include curl перенеси в cpp.

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

например венда и андроид

Мы тут как бы на ЛОРе сидим, и мастдаища не касаемся. Как и остальных анально огороженных поделок.

никогда не знаешь какая версия курла окажется у юзера

И таки шо? Сложно проверить? Cmake тебе зачем?

дремучая

Хай обновляет.

придется, как Зенитару, собирать свой проект на дремучей центоси

Извращенец!

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

Мы тут как бы на ЛОРе сидим, и мастдаища не касаемся. Как и остальных анально огороженных поделок.

ну не все же, как ты, ограничивают себя только лором и линуксом.

И таки шо? Сложно проверить? Cmake тебе зачем?

я предпочитаю юзерам отдавать бинари, а не исходники.

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

Писать Makefile'ы в тысячи строк вручную — это полный бульбец!

а прикинь, если вножную - это просто мега-бульбец!

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

насчет тысяч строк ты таки загнул...

$ find ~/prj/deadbeef -name "Makefile.am" | xargs wc -l | awk '{printf "%03d %s\n", $1, $2}' | sort | tail -n 1
406 /home/waker/prj/deadbeef/plugins/gme/Makefile.am

(бОльшая часть строк — имена файлов, которые я ессно вручную не пишу)

waker ★★★★★
()
Последнее исправление: waker (всего исправлений: 1)

Ну вы народ даете, девушку совсем заморочили 1. автотулз легки и приятны по сравнению с cmake и писать под него значительно легче, 2. штатными средствами никак не сделать статическую либу, содержащую все зависимости. можно руками arом разобрать архивы и собрать в один, но будет огромный размер, к тому же не все либы принципиально могут так работать. Конкретный curl так можно включить, если у него позволяет лицензия.

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

Проблема в другом. Планируется сделать библиотеку => для доступа к классам/функциям нужен *.h. Но! в A.h уже *включено* требование curl.h => надо ставить curl не зависимо от типа сборки. Epic fail.

Одно из решений проблемы примитивное — написать новый заголовочный файл («обертку») в который выводить только внешние функции, а сам класс А «спрятать». Например, что то такое

#ifndef _MYLIB_A_H_
#define _MYLIB_A_H_

#ifdef __cplusplus
class A;
typedef A_ptr* A;
extern "C"{ // неплохо бы позаботиться о тех кто не любит С++
#else
typedewf A_ptr* void;
#endif
A_ptr *mylib_create_A(); // вызывает конструктор
void mylib_delete_A(A_ptr *); // вызывает деструктор
void mylib_A_Method(A_ptr *); // пошли методы класса
...
#ifdef __cplusplus
}
class mylibA // класс для пользователя
{
  A_ptr *self;
public:
  mylibA() { self=mylib_create_A(); }
  ~mylibA(){ mylib_delete_A(self);  }
  void Method() { mylib_A_Method(self); }
};
#endif

#endif
В результате:

  • curl нигде не упоминается и не нужен, а собирать можно хоть статически, хоть динамически (только предоставить библиотеку curl тоже придется);
  • библиотеку можно использовать из любых языков/компиляторов без пересборки бинарников — С-ые функции вызываются откуда хочешь, а вот у С++ функций переносимость хуже;
  • ABI библиотеки фиксирован и его испортить сложно, чтобы в исходном классе A не менялось — полезно для развития библиотеки;
  • дополнительный префикс у класса mylibA и функций позволяет избежать конфликта имен у пользователей. При этом неплохо бы пометить все внутренние классы/функции как не экспортируемые.

Соответственно, сам файл A.h (и класс A) отдавать наружу совершенно не обязательно.

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

И таки шо? Сложно проверить? Cmake тебе зачем?

я предпочитаю юзерам отдавать бинари, а не исходники.

Хмм, если не open-source, то Ваше личное дело, хотя иногда приходится и исходниками делиться ...

А вообще-то cmake — наиболее простой кросс-платформенный полуавтоматический инструмент для поиска/задания всех зависимостей, флагов, опций и пр ... Ручками бывает сложно, когда проект может зависеть от пары десятков внешних библиотек (которые можно выборочно отключать), и предоставляет десяток бинарных файлов (исполняемых и библиотек)

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

Опс, в классе mylibA должно быть конечно же

A_ptr self;

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

а что, CMakeList.txt вы не руками пишете, или я чето не догоняю?

в общем, спасибо за советы конечно, но я cmake ненавижу не потому, что не знаю что это такое, а как раз потому что знаю и сталкивался. более говняной билд-системы еще поискать недо.

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

а что, CMakeList.txt вы не руками пишете, или я чето не догоняю?

Прикол в том, что CMakeList.txt пишется легко и непринужденно. А Makefile вручную писать — жуткий ад, особенно если нужно кучу зависимостей учесть.

Скажем (было у меня такое), нужно тебе узнать, есть ли у пользователя CUDA, а если есть, то что за возможности у видеокарты. При помощи cmake это легко делается, а если вручную в Makefile писать, боюсь, получится несколько страниц!

более говняной билд-системы еще поискать надо

А что искать? autotools же!

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

я использую autotools для больших проектов, и plain makefiles для мелких.

считаю пользователей cmake ниасиляторами, а девелоперов, которые релизят софт с cmake вместо билд-системы - подлыми мудаками.

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

Причем, в отличие от языка Makefile, язык cmake понятен.

может тебе еще и питон нравится? а то я такие аргументы часто слышу от питонистов, что мол «язык перл непонятен».

мне вот все понятно, и make, и automake, и cmake. и из них cmake самый идиотский.

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

Ну ты даешь! Да, cmake не идеален. Но autotools точно мудаками создан: если на тестирование и генерирование Makefile'а у cmake уходит пару секунд, то automake будет минуты три возиться! Вот оно — извращение!

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

если на тестирование и генерирование Makefile'а у cmake уходит пару секунд, то automake будет минуты три возиться

automake не генерирует makefile'ы. их генерирует configure. генерация makefile'ов занимает считаные доли секунды. остальное время занимает проверка зависимостей и конфигурация системы сборки. медленно, зато надежно. и главное - работает.

а cmake за кажущейся простотой позволяет писать кривые makefiles, которые в итоге работают только на машине девелопера.

а что насчет идиотского синтаксиса вместо --prefix, который каждый раз гуглить приходится, ибо запомнить нереально?

пробовал ли ты когда-нибудь собрать серию взаимо-зависимых cmake проектов куда-нибудь в $HOME/build? попробуй, получишь много радости.

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

медленно, зато надежно

Не медленно, а жутко медленно. Cmake лучше.

а cmake за кажущейся простотой позволяет писать кривые makefiles

А то ты не напишешь кривые makefile'ы в автомейке!

что насчет идиотского синтаксиса

Один раз потратил время, набросал "рыбу", а потом постоянно ею пользуешься. Удобно.

пробовал ли ты когда-нибудь собрать серию взаимо-зависимых cmake проектов куда-нибудь в $HOME/build?

Нафига?

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

А то ты не напишешь кривые makefile'ы в автомейке!

а автотулсах есть средства тестирования, чтобы убедиться, что makefiles не кривые, до релиза. вероятность выпустить проект с кривой системой сборки на порядок ниже, чем с cmake.

Один раз потратил время, набросал «рыбу», а потом постоянно ею пользуешься. Удобно.

что за рыба еще?

Нафига?

как нафига? в cmake ведь нету make uninstall, не так ли? во всяком случае, по умолчанию точно нет, и большинство девелоперов не парятся.

если насрал в /usr каким-то дерьмом — его ведь уже не вытащить оттуда.

если я хочу попробовать новую версию какого-то проекта - я собираю и запускаю в $HOME.

(тут наверное стоит уточнить — собираю и запускаю в $HOME только если есть нормальная работающая система сборки. с cmake это пока у меня ни разу не получилось сделать)

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

Не медленно, а жутко медленно. Cmake лучше.

Cmake быстрее, потому что он НИЧЕГО не делает.

Основное время работы при конфигурирование пакета - это компиляция и запуск маленьких программок.

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

automake не генерирует makefile'ы. их генерирует configure. генерация makefile'ов занимает считаные доли секунды. остальное время занимает проверка зависимостей и конфигурация системы сборки. медленно, зато надежно. и главное - работает.

Меня как раз волнует полное время сборки, а не то куда оно потрачено. У cmake с этим лучше.

а cmake за кажущейся простотой позволяет писать кривые makefiles, которые в итоге работают только на машине девелопера.

Ой, все программы можно написать криво ... Но мой опыт показывает, что переносимость и удобство у cmake выше.

а что насчет идиотского синтаксиса вместо --prefix, который каждый раз гуглить приходится, ибо запомнить нереально?

Зачем если есть cmake-gui ?

пробовал ли ты когда-нибудь собрать серию взаимо-зависимых cmake проектов куда-нибудь в $HOME/build? попробуй, получишь много радости.

Не поверите, но приходится это делать регулярно причем на куче систем (Ubuntu i386, Ubuntu amd64, WinXP 32bit и Win7 64bit).

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

CMakeLists.txt, который ты везде используешь с минимальными правками. Удобно.

так вся соль в том, что я не использую cmake. я просто хочу собрать проект, который использует, в определенный префикс. и каждый раз надо лезть в гугл. потому что синтаксис идиотский и не запоминающийся.

и я пользуюсь разными компьютерами, на разных осях, в разных местах. поэтому написать некий cmakelists.txt, который я буду везде использовать, несколько затруднительно. его на флешке тогда придется таскать, или хранить в каком-то дропбоксе, а это ничем не лучше чем гуглить каждый раз.

Да ну!

читать умеешь?

по дефолту его нет. во многих проектах его нет.

вобщем, еще один минус cmake.

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