dlopen()
ist eine C-Funktion, die zum dynamischen Laden von gemeinsam genutzten Bibliotheken zur Laufzeit verwendet wird. Das Muster, falls Sie nicht vertraut sind, ist also:
dlopen("libpath", flag)
auf, um ein void *handle
für die Bibliothek dlsym(handle, "object_name")
auf, um eine void *object
von der Bibliothek object
dlclose (handle)
auf, um die Bibliothek zu entladen. Dies ist in C ++ ein perfekter Anwendungsfall für den sogenannten Aliasing-Konstruktor von std::shared_ptr
. Das Muster wird:
std::shared_ptr<void> handle
von dlopen("libpath", flag)
, das dlclose()
aufruft, wenn sein Destruktor std::shared_ptr<void> object
von handle
und dlsym(handle, "object_name")
object
wo auch immer wir wollen weitergeben und total handle
vergessen; Wenn der Destruktor von object
aufgerufen wird, wird dlclose()
automatisch aufgerufen Brilliantes Muster, und es funktioniert wunderbar. Ein kleines Problem. Das obige Muster erfordert eine Umwandlung von void*
nach whatever_type_object_is*
. Wenn sich "object_name"
auf eine Funktion bezieht (was die meiste Zeit unter Berücksichtigung des Anwendungsfalles tut), ist dies ein undefiniertes Verhalten.
In C gibt es einen Hack, um das zu umgehen. Von der dlopen
man-Seite:
was offensichtlich gut funktioniert, in C. Aber gibt es einen einfachen Weg, dies mit std::shared_ptr
zu machen?
Das obige Muster erfordert eine Umwandlung von void * nach whatever_type_object_is *. Wenn sich "object_name" auf eine Funktion bezieht (was meistens unter Berücksichtigung des Anwendungsfalles geschieht), ist dies ein undefiniertes Verhalten.
Nun, das ist nicht ganz richtig, zumindest in C ++ wird es nur bedingt unterstützt.
5.2.10.8 sagt:
Das Konvertieren eines Funktionszeigers in einen Objektzeigertyp oder umgekehrt wird bedingt unterstützt. Die Bedeutung Eine solche Konvertierung ist implementierungsdefiniert, außer dass eine Implementierung Konvertierungen unterstützt beide Richtungen, Umwandlung eines Pr-Wertes eines Typs in den anderen Typ und zurück, möglicherweise mit anderer C-Qualifizierung, soll den ursprünglichen Zeigerwert ergeben.
Wenn man also davon ausgeht, dass dlsym
intern einen Funktionszeiger auf ein void*
wirft, glaube ich, dass es in Ordnung ist, wenn man es einfach auf einen Funktionszeiger zurückwirft.
Tags und Links c++ c++11 undefined-behavior shared-libraries shared-ptr