Короткий ответ
Это не сработает так, как вы это делаете.В вашем подходе могут быть и другие проблемы, которые вас еще не укусили.
Почему это не работает
Неопределенные символы в вашей программе / библиотеке решаются в разное время.В большинстве систем ссылки на данные (глобальные переменные, таблицы классов и т. Д.) Всегда разрешаются при загрузке вашей программы / библиотеки.Ссылки на код разрешаются, когда они впервые используются в некоторых системах («отложенный поиск»; по крайней мере, это происходит в Linux и Mac OS X), если не установлены некоторые специальные параметры (параметр RTLD_NOW для dlopen или переменная среды LD_BIND_NOW).Как только они будут решены, новый поиск не будет выполнен.
Если вы dlopen
отметили вашу библиотеку с флагом RTLD_GLOBAL до того, как ленивый поиск метода будет завершен, будет использован метод из вашей библиотеки.Ссылка на код метода теперь разрешена;это не изменится снова.Ваша основная программа теперь официально использует символы из вашей dlopen
ed библиотеки, поэтому dlclose
больше не будет закрывать библиотеку - dlclose
только сбрасывает на нее ваш явный дескриптор.
Короче говоря, вы должны толькоожидайте выгрузки библиотек, которые вы используете только через явные вызовы dlsym
.
Что вместо этого сделать
Что вы вместо этого можете сделать, это предоставить вашей библиотеке производнуюреализация класса.Вы бы определили свой класс C
как абстрактный базовый класс:
class C
{
public:
virtual void method();
};
В вашей отдельно скомпилированной библиотеке вы бы определили производный класс и функцию, которая создает объект этого производного класса:
class D : public C
{
public:
virtual void method();
};
void D::method()
{
// ...
}
extern "C" C* createC()
{
return new D();
}
Теперь в вашей основной программе вы загрузите библиотеку с помощью dlopen
, получите указатель функции на createD
с помощью dlsym
и вызовете ее, чтобы получить объект.Когда все объекты исчезнут, вы можете вызвать dlclose
, перекомпилировать вашу библиотеку и снова выполнить все это:
typedef C* (*creatorFunction)();
int main()
{
for(;;)
{
void *handle = dlopen("mylib.so", 0);
creatorFunction create = (creatorFunction) dlsym(handle, "createC");
C *c = (*create)();
c->method();
delete c;
dlclose(handle);
char pause;
cin << pause;
}
return 0;
}