2009-11-05 8 views
9

Я разрабатываю общую библиотеку с использованием C++ в Linux, и я хотел бы, чтобы эта библиотека использовала log4cxx для ведения журнала. Однако я не уверен, как это сделать. Для работы log4cxx мне нужно создать объект журнала. Как я могу убедиться, что этот объект создан при загрузке моей библиотеки?Как инициализировать общую библиотеку в Linux

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

Я знаю, что в DLL для Windows есть что-то вроде REASON_FOR_CALL == PROCESS_ATTACH; есть ли что-то подобное в Linux?

ответ

16

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

Если вам нужно произвольную функцию, которая будет вызвана, когда библиотека загружается, используйте атрибут конструктора для GCC: функции

__attribute__((constructor)) void foo(void) { 
    printf("library loaded!\n"); 
} 

Конструкторы вызываются с помощью динамического компоновщика, когда библиотека загружается. На самом деле, как реализуется глобальная инициализация C++.

+0

Это справедливо и для библиотек C. Существует также '__attribute __ ((destructor))' для функции, вызываемой при выгрузке библиотеки –

+0

... и этот атрибут не имеет ничего общего с конструкцией объекта? – einpoklum

+0

@einpoklum, справа, это в основном не связано с построением объекта. Вы можете использовать его в C, который не имеет объектов. Тем не менее, C++ использует это внутренне для вызова конструкторов и деструкторов глобальных объектов. –

10

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

namespace { 
    struct initializer { 
    initializer() { 
     std::cout << "Loading the library" << std::endl; 
    } 

    ~initializer() { 
     std::cout << "Unloading the library" << std::endl; 
    } 
    }; 
    static initializer i; 
} 
+1

Можете ли вы объяснить, почему ваш ответ лучше всего использовать глобалы и не делать ничего особенного? – einpoklum

+0

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

3

Использование глобальной (или локальной статической завернутые в функции) хорошо ... но тогда вы введите страну статического фиаско инициализации (и фактическое разрушение тоже не очень).

Я бы порекомендовал взглянуть на реализацию Loki Singleton.

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

Когда вы на нем, ознакомьтесь с Modern C++ Design, в котором объясняются проблемы, с которыми сталкивается Singleton в глубину, а также использование различных политик.

+1

+1 для использования слова «фиаско», чтобы описать, что другие могут назвать «ад». :) – unwind

+2

Fiasco - это глупая концепция, поднятая этим страшным сайтом C++ FAQ. Его не фиаско и комментарий даже не актуальны в этой области, так как не существует никакой связи между глобальными переменными. –

+2

Позвольте мне не согласиться с Мартином, но искушение ловить строительство или разрушение глобальных объектов реально. –

Смежные вопросы