dlopen()
是用于在运行时动态加载共享库的 C 函数。如果您不熟悉,该模式是这样的:
- 打电话
dlopen("libpath", flag)
去void *handle
图书馆 - 打电话从图书馆
dlsym(handle, "object_name")
拿void *object
你想要的东西 - 做你想做的事
object
- 调用
dlclose (handle)
卸载库。
在 C++ 中,这是所谓的别名构造函数的完美用例std::shared_ptr
。模式变为:
- 构造一个
std::shared_ptr<void> handle
将在dlopen("libpath", flag)
调用dlclose()
其析构函数时调用的 std::shared_ptr<void> object
从handle
and构造一个dlsym(handle, "object_name")
- 现在我们可以去
object
任何我们想去的地方,完全忘记handle
;当object
's 的析构函数被调用时,无论何时发生,dlclose()
都会被自动调用
图案精美,效果很好。不过有一个小问题。上面的模式需要从void*
to强制转换whatever_type_object_is*
。如果"object_name"
引用一个函数(考虑到用例,它在大多数情况下都会这样做),这是未定义的行为。
在 C 中,有一个 hack 可以解决这个问题。从dlopen
手册页:
// ...
void *handle;
double (*cosine)(double);
// ...
handle = dlopen("libm.so", RTLD_LAZY);
// ...
/* Writing: cosine = double (*)(double)) dlsym(handle, "cos");
would seem more natural, but the C99 standard leaves
casting from "void *" to a function pointer undefined.
The assignment used below is the POSIX.1-2003 (Technical
Corrigendum 1) workaround; see the Rationale for the
POSIX specification of dlsym(). */
*(void **) (&cosine) = dlsym(handle, "cos");
// ...
这显然工作得很好,在 C 中。但是有没有一种简单的方法可以做到这一点std::shared_ptr
?