Revision: 75390
http://sourceforge.net/p/brlcad/code/75390
Author: starseeker
Date: 2020-04-14 14:23:52 +0000 (Tue, 14 Apr 2020)
Log Message:
-----------
Put together a (relatively) minimal exercising of the bu_dlopen et. al. API
that lets us do runtime loadable plugins.
Modified Paths:
--------------
brlcad/trunk/src/libbu/tests/CMakeLists.txt
brlcad/trunk/src/libbu/tests/dylib/CMakeLists.txt
brlcad/trunk/src/libbu/tests/dylib/dylib.c
brlcad/trunk/src/libbu/tests/dylib/dylib.h
brlcad/trunk/src/libbu/tests/dylib/run.c
Modified: brlcad/trunk/src/libbu/tests/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/libbu/tests/CMakeLists.txt 2020-04-14 12:05:01 UTC (rev
75389)
+++ brlcad/trunk/src/libbu/tests/CMakeLists.txt 2020-04-14 14:23:52 UTC (rev
75390)
@@ -737,7 +737,7 @@
#
# *********** bu_dlopen/bu_dlsym test ************
#
-#add_subdirectory(dylib)
+add_subdirectory(dylib)
CMAKEFILES(
tests_bitv.cmake
Modified: brlcad/trunk/src/libbu/tests/dylib/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/libbu/tests/dylib/CMakeLists.txt 2020-04-14 12:05:01 UTC
(rev 75389)
+++ brlcad/trunk/src/libbu/tests/dylib/CMakeLists.txt 2020-04-14 14:23:52 UTC
(rev 75390)
@@ -8,17 +8,27 @@
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${LIBEXEC_DIR}/dylib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${LIBEXEC_DIR}/dylib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${LIBEXEC_DIR}/dylib"
-)
+ )
add_library(libdylib SHARED dylib.c)
if (CPP_DLL_DEFINES)
- set_property(TARGET plugin_1 APPEND PROPERTY COMPILE_DEFINITIONS
BU_DYLIB_EXPORTS)
- set_property(TARGET plugin_2 APPEND PROPERTY COMPILE_DEFINITIONS
BU_DYLIB_EXPORTS)
- set_property(TARGET libdylib APPEND PROPERTY COMPILE_DEFINITIONS
BU_DYLIB_EXPORTS)
+ set_property(TARGET plugin_1 APPEND PROPERTY COMPILE_DEFINITIONS
BU_DYLIB_EXPORTS)
+ set_property(TARGET plugin_2 APPEND PROPERTY COMPILE_DEFINITIONS
BU_DYLIB_EXPORTS)
+ set_property(TARGET libdylib APPEND PROPERTY COMPILE_DEFINITIONS
BU_DYLIB_EXPORTS)
endif (CPP_DLL_DEFINES)
add_executable(bu_dylib run.c)
target_link_libraries(bu_dylib libdylib libbu)
if (CPP_DLL_DEFINES)
- set_property(TARGET bu_dylib APPEND PROPERTY COMPILE_DEFINITIONS
BU_DYLIB_IMPORTS)
+ set_property(TARGET bu_dylib APPEND PROPERTY COMPILE_DEFINITIONS
BU_DYLIB_IMPORTS)
endif (CPP_DLL_DEFINES)
+
+
+add_test(NAME bu_dylib COMMAND bu_dylib)
+
+# Local Variables:
+# tab-width: 8
+# mode: cmake
+# indent-tabs-mode: t
+# End:
+# ex: shiftwidth=2 tabstop=8
Modified: brlcad/trunk/src/libbu/tests/dylib/dylib.c
===================================================================
--- brlcad/trunk/src/libbu/tests/dylib/dylib.c 2020-04-14 12:05:01 UTC (rev
75389)
+++ brlcad/trunk/src/libbu/tests/dylib/dylib.c 2020-04-14 14:23:52 UTC (rev
75390)
@@ -11,9 +11,8 @@
#include "dylib.h"
int
-dylib_load_plugins()
+dylib_load_plugins(struct bu_ptbl *plugins, struct bu_ptbl *dl_handles)
{
- static struct bu_ptbl plugins = BU_PTBL_INIT_ZERO;
const char *ppath = bu_dir(NULL, 0, BU_DIR_LIBEXEC, "dylib", NULL);
char **filenames;
const char *psymbol = "dylib_plugin_info";
@@ -32,6 +31,9 @@
bu_log("Unable to dynamically load '%s' (skipping)\n", pfile);
continue;
}
+ if (dl_handles) {
+ bu_ptbl_ins(dl_handles, (long *)dl_handle);
+ }
info_val = bu_dlsym(dl_handle, psymbol);
const struct dylib_plugin *(*plugin_info)() = (const struct
dylib_plugin *(*)())(intptr_t)info_val;
if (!plugin_info) {
@@ -53,12 +55,25 @@
}
const struct dylib_contents *pcontents = plugin->i;
- bu_ptbl_ins(&plugins, (long *)pcontents);
+ bu_ptbl_ins(plugins, (long *)pcontents);
}
- return (nfiles == BU_PTBL_LEN(&plugins));
+ return BU_PTBL_LEN(plugins);
}
+int
+dylib_close_plugins(struct bu_ptbl *plugins)
+{
+ int ret = 0;
+ for (size_t i = 0; i < BU_PTBL_LEN(plugins); i++) {
+ if (bu_dlclose((void *)BU_PTBL_GET(plugins, i))) {
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
/*
* Local Variables:
* tab-width: 8
Modified: brlcad/trunk/src/libbu/tests/dylib/dylib.h
===================================================================
--- brlcad/trunk/src/libbu/tests/dylib/dylib.h 2020-04-14 12:05:01 UTC (rev
75389)
+++ brlcad/trunk/src/libbu/tests/dylib/dylib.h 2020-04-14 14:23:52 UTC (rev
75390)
@@ -1,12 +1,42 @@
+#include "common.h"
+#include "bu/ptbl.h"
+
+#ifndef BU_DYLIB_EXPORT
+# if defined(BU_DYLIB_DLL_EXPORTS) && defined(BU_DYLIB_DLL_IMPORTS)
+# error "Only BU_DYLIB_DLL_EXPORTS or BU_DYLIB_DLL_IMPORTS can be defined,
not both."
+# elif defined(BU_DYLIB_DLL_EXPORTS)
+# define BU_DYLIB_EXPORT __declspec(dllexport)
+# elif defined(BU_DYLIB_DLL_IMPORTS)
+# define BU_DYLIB_EXPORT __declspec(dllimport)
+# else
+# define BU_DYLIB_EXPORT
+# endif
+#endif
+
struct dylib_contents {
- const char *const name;
- double version;
- int (*calc)(char **result, int rmaxlen, int input);
+ const char *const name;
+ double version;
+
+ int (*calc)(char **result, int rmaxlen, int input);
};
struct dylib_plugin {
- const struct dylib_contents * const i;
+ const struct dylib_contents * const i;
};
-extern int dylib_load_plugins();
+// Load all plugins present in the LIBEXEC_PLUGINS/dylib directory.
Optionally return
+// handles in a second table to allow the calling of dylib_close_plugins.
+BU_DYLIB_EXPORT extern int dylib_load_plugins(struct bu_ptbl *plugins, struct
bu_ptbl *handles);
+// If we stored handles when calling dylib_load_plugins, we can close them
with this call.
+BU_DYLIB_EXPORT extern int dylib_close_plugins(struct bu_ptbl *handles);
+
+/*
+ * Local Variables:
+ * tab-width: 8
+ * mode: C
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */
Modified: brlcad/trunk/src/libbu/tests/dylib/run.c
===================================================================
--- brlcad/trunk/src/libbu/tests/dylib/run.c 2020-04-14 12:05:01 UTC (rev
75389)
+++ brlcad/trunk/src/libbu/tests/dylib/run.c 2020-04-14 14:23:52 UTC (rev
75390)
@@ -1,8 +1,77 @@
#include "common.h"
+#include "bu.h"
#include "dylib.h"
int main() {
- return dylib_load_plugins();
+ int expected_plugins = 2;
+ struct bu_ptbl plugins = BU_PTBL_INIT_ZERO;
+ struct bu_ptbl handles = BU_PTBL_INIT_ZERO;
+ int pcnt = dylib_load_plugins(&plugins, &handles);
+ if (pcnt != expected_plugins) {
+ bu_log("Expected %d plugins, found %d.\n", expected_plugins, pcnt);
+ bu_ptbl_free(&plugins);
+ (void)dylib_close_plugins(&handles);
+ bu_ptbl_free(&handles);
+ return -1;
+ }
+
+ int expected_results = 1;
+ for (size_t i = 0; i < BU_PTBL_LEN(&plugins); i++) {
+ const struct dylib_contents *p = (const struct dylib_contents
*)BU_PTBL_GET(&plugins, i);
+ if (BU_STR_EQUAL(p->name, "Plugin 1")) {
+ // Check that plugin 1 does what we expect
+ double eversion = 1.0;
+ if (!NEAR_EQUAL(p->version, eversion, SMALL_FASTF)) {
+ bu_log("%s: expected version %f plugins, found %f.\n", p->name,
eversion, p->version);
+ expected_results = 0;
+ }
+ int rstr_len = 10;
+ char *cresult = (char *)bu_calloc(rstr_len, sizeof(char), "result
buffer");
+ int calc_test = p->calc((char **)&cresult, rstr_len, 2);
+ if (calc_test) {
+ bu_log("%s: plugin reports insufficient space in results
buffer.\n", p->name);
+ expected_results = 0;
+ }
+ const char *ecalc = "4";
+ if (!BU_STR_EQUAL(cresult, ecalc)) {
+ bu_log("%s: expected to calculate %s, got %s.\n", p->name,
ecalc, cresult);
+ expected_results = 0;
+ }
+ bu_free(cresult, "result container");
+ }
+ if (BU_STR_EQUAL(p->name, "Plugin 2")) {
+ // Check that plugin 2 does what we expect
+ double eversion = 2.3;
+ if (!NEAR_EQUAL(p->version, eversion, SMALL_FASTF)) {
+ bu_log("%s: expected version %f plugins, found %f.\n", p->name,
eversion, p->version);
+ expected_results = 0;
+ }
+ int rstr_len = 10;
+ char *cresult = (char *)bu_calloc(rstr_len, sizeof(char), "result
buffer");
+ int calc_test = p->calc((char **)&cresult, rstr_len, 4);
+ if (calc_test) {
+ bu_log("%s: plugin reports insufficient space in results
buffer.\n", p->name);
+ expected_results = 0;
+ }
+ const char *ecalc = "400";
+ if (!BU_STR_EQUAL(cresult, ecalc)) {
+ bu_log("%s: expected to calculate %s, got %s.\n", p->name,
ecalc, cresult);
+ expected_results = 0;
+ }
+ bu_free(cresult, "result container");
+ }
+ }
+
+ bu_ptbl_free(&plugins);
+
+ if (dylib_close_plugins(&handles)) {
+ bu_log("bu_dlclose failed to unload plugins.\n");
+ expected_results = 0;
+ }
+ bu_ptbl_free(&handles);
+
+ // If everything is as expected, return 0
+ return (!expected_results);
}
/*
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits