Как я могу автоматически зарегистрировать объекты C++ с фабрикой, когда эти объекты находятся в отдельных общих библиотеках?
У меня есть ситуация, когда я хотел бы создать библиотеку, которая содержит фабрику, назовем ее FooFactory, для производных классов из общего базового класса, я назову это IFoo. Затем у меня есть множество объектов Foo1, Foo2 и т. Д., Которые являются производными от IFoo, но которые объявлены в отдельных общих библиотеках.
Когда Foo1, Foo2 и т. Д. Находятся в одной библиотеке, я могу определить статические глобальные объекты InitializeFoo1, InitializeFoo2 и т. Д., Которые в своих конструкторах регистрируют метод create для этого класса с помощью фабрики. Однако, когда они находятся в отдельных библиотеках, эти объекты инициализатора никогда не создаются, поэтому производные классы никогда не регистрируются.
Мое предыдущее исследование показало, что если бы эти библиотеки были статически связаны, иначе никогда не использовались, инициализаторы могли бы быть удалены, а их конструкторы никогда не вызываться, но так ли это и для разделяемых библиотек? Если да, есть ли какой-нибудь способ убедиться, что эти объекты инициализатора созданы? Наконец, если я просто "делаю все неправильно", я, конечно, открыт для любых советов о том, как лучше поступить.
Должен также отметить, что этот вопрос представляется здесь пассивным. В этом случае предлагаемый ответ на исходный вопрос предполагает такой статический объект инициализатора, но спрашивающий комментирует, что он не работает по той же причине, по которой у меня есть - что инициализатор никогда не создается, - но этот комментарий по существу остается безадресным.
Некоторый контекст: все это происходит на машине Linux, я компилирую с gcc 4.7.3. Если это вообще помогает, то причина для всего этого - позволить разработчикам создавать новые производные объекты, которые могут быть связаны с кодом без изменения или перекомпиляции существующей базы кода. (Новые объекты создаются на основе событий времени выполнения.)
1 ответ
Я протестировал описанный вами случай на RHEL 5.7 с gcc 4.1.2, и глобальная статика создается также при определении в разделяемой библиотеке. Если основной связан с общей библиотекой с g++ -l lib
вариант, чем конструктор вызывается до main()
как ожидается, и если библиотека загружается вручную с помощью dlopen()
Вызовите, естественно, он создается при загрузке библиотеки. Но он строится автоматически в обоих случаях.
В любом случае, возможно, в качестве обходного пути вы можете определить "конструктор" для разделяемой библиотеки, то есть функцию, которая вызывается системой при загрузке библиотеки, и определить, что вы инициализируете объект как статический внутри функции? Синтаксис для этого следующий:
extern "C" {
void __attribute__ ((constructor)) libload(void)
{
cout << "dll ctor called\n";
static A a;
}
void __attribute__ ((destructor)) libunload(void)
{
}
} // extern