Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Как правильно экспортировать класс из динамической библиотеки (*.so) Linux С++

#cpp #linux #g++ #export #so


Продолжаю изучать программирование под линукс. Хотелось бы спросить совета, как верно
прописать экспорт класс из динамической библиотеки в линуксе ? Тестовый проект пишу
на C++. 

Есть тестовый класс обозначенный :

class Book
{
private:
    int m_year;
    std::string m_author;
    std::string m_bookName;

public:

    Book(int year=0, const char* author="Default", const char* bookName="Default"):
        m_year{year},
        m_author{author},
        m_bookName{bookName}
    {
    }

    std::string getStr();

    int getYear();
};


Этот класс и будет вынесен в динамическую библиотеку.

Подскажите как правильно его экспортировать что бы он был доступен в проектах использующих
данную библиотеку ? В сети много информации по экспорту C функций но не смог найти
не чего дельного по экспорту классов под линукс.

Компилирую следующим образом:

g++ -shared -o libBook.so -Wall -fPIC Book.h Book.cpp 


Нашел способ - использование атрибута:

__attribute__((visibility("default")))


Вроде работает. Есть ли еще какие нибудь пути ? на сколько этот способ верен ?
или же можно вовсе не указывать не какого атрибута ? Все равно программка работает
и использует класс Book.
    


Ответы

Ответ 1



Для начала, при сборке elf с помощью gcc в linux все символы видимы по умолчанию, т.е. простой сборки. g++ -shared -o libBook.so -Wall -fPIC Book.h Book.cpp Уже достаточно, чтобы интерфейс Book оказался видимым (экспортированным в терминах MS). Но, конечно, ради чистоты хорошей практикой является ограничивать интерфейс библиотек (здесь описано почему), Как собственно скрыть символы Для того чтобы gcc скрывал символы по умолчанию нужно явно передать ему ключ -fvisibility=hidden. А для того чтобы сделать видимыми отдельные символы необходимо пометить их с помощью соответствующего атрибута: class __attribute__((visibility("default"))) Book; или в стиле С++11: class [[gnu::visibility("default")]] Book; Аналогично можно сделать символ явно скрытым: class __attribute__((visibility("hidden"))) BookInternalImp; Применять эти атрибуты к объявлениям вполне достаточно. Указывать их для определения каждой функции не обязательно. Но можно, например, спрятать отдельные статические члены и функции-члены класса: class [[gnu::visibility("default")]] Book { private: void [[gnu::visibility("hidden")]] doSomeInternalProcessing(); static BookManager* [[gnu::visibility("hidden")]] internalManager; } Также можно воспользоваться прагмой с аналогичным эффектом на серию последовательных объявлений (но на отдельные члены классов эти прагмы не подействуют): #pragma GCC visibility push(visibility) class Book; class Author; #pragma GCC visibility pop Есть и другие значения атрибута visibility: protected и internal, но пользы от них не так много и поэтому о них обычно мало-кто помнит (см. подробности в документации).

Комментариев нет:

Отправить комментарий