dlopen()
is a C function used for dynamically loading shared libraries at runtime. The pattern, in case you're not familiar, is thus:
- Call
dlopen("libpath", flag)
to get avoid *handle
to the library - Call
dlsym(handle, "object_name")
to get avoid *object
to the thing you want from the library - Do what you want with
object
- Call
dlclose (handle)
to unload the library.
This is, in C++, a perfect use-case for the so-called aliasing constructor of std::shared_ptr
. The pattern becomes:
- Construct a
std::shared_ptr<void> handle
fromdlopen("libpath", flag)
that will calldlclose()
when its destructor is called - Construct a
std::shared_ptr<void> object
fromhandle
anddlsym(handle, "object_name")
- Now we can pass
object
wherever we want, and completely forget abouthandle
; whenobject
's destructor is called, whenever that happens to be,dlclose()
will be called automagically
Brilliant pattern, and it works beautifully. One small problem, though. The pattern above requires a cast from void*
to whatever_type_object_is*
. If "object_name"
refers to a function (which most of the time it does, considering the use-case), this is undefined behavior.
In C, there is a hack to get around this. From the dlopen
man page:
// ...
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");
// ...
which obviously works just fine, in C. But is there an easy way to do this with std::shared_ptr
?
std::shared_ptr
to the poointer, returned by dlsym? – Shuckdlclose
when there is that pointer). – Flowerstd::shared_ptr
allows twostd::shared_ptr
s to share the same "close condition" (my term, not official) without pointing to the same object or even the same type. Using astd::shared_ptr
for the value returned bydlsym()
gains me this benefit: the lifetime of the library is tied to the lifetime ofobject
. – Shannashannahshared_ptr
) ? – Flowerstd::shared_ptr
to library handle and havestd::shared_ptr
to that structure. You may loose coolness of using "close condition" but that should work. – Shuckdlopen
provide any guarantees about what happens? I guess not. – Aqua