我想我可以在共享库中实现类的一部分,只要在使用时加载符号。
myclass.h
---
class C {
void method();
}
main.cpp
---
#include "myclass.h"
int main() {
//dynamically load mylib.so using dlopen/dlsym/dlclose
...
C *c = new C();
c->method();
delete c;
}
mylib.so compiled separately:
====
mylib.cpp
---
#include "mylib.h"
void C::method() {
...
}
这很好用。
但是一旦我完成了使用C :: method(),我想卸载它,所以我可以更改,重新编译并重新加载它而无需重新启动主程序
int main() {
//dynamically load mylib.so using dlopen/dlsym/dlclose
...
C *c = new C();
c->method();
delete c;
// close the lib, remove the handle...
....
char pause;
cin << pause; // before carrying on change the C::method, recompile it
//dynamically load *Again* mylib.so using dlopen/dlsym/dlclose
...
C *c = new C();
c->method();
delete c;
}
问题是它在执行第一个dlclose时没有卸载库,可能是因为我的类C的实例存在。有什么方法可以强迫这个?
(在Linux Ubuntu 10.04上使用g ++ 4.2.3)
它不会像你那样工作。你的方法可能还有其他问题,但还没有让你感到困惑。
程序/库中未定义的符号将在不同时间解析。在大多数系统上,加载程序/库时始终会解析数据引用(全局变量,类vtable等)。首次在某些系统上使用代码引用时会解析(“延迟查找”;至少在Linux和Mac OS X上发生),除非设置了一些特殊选项(dlopen或LD_BIND_NOW环境变量的RTLD_NOW参数)。一旦解决了这些问题,就不会进行新的查找。
如果在完成方法的延迟查找之前,使用RTLD_GLOBAL标志对库进行dlopen
,则将使用库中的方法。现在解决了该方法的代码引用;它不会再改变。您的主程序现在正式使用来自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;
}
谢谢你的帮助,只是一个通知:
不要忘记在C类中将方法初始化为零(此类不在共享库中),并将虚拟驱逐舰设置为默认值
如果你想知道dlopen的标志是0 - >它是RTLD_LOCAL