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

Reply via email to