}
cl_object
+si_unload_foreign_module(cl_object module)
+{
+#if !defined(ENABLE_DLOPEN)
+ FEerror("SI:UNLOAD-FOREIGN-MODULE does not work when ECL is statically linked", 0);
+#else
+ cl_object output = ECL_NIL;
+
+ if (ecl_unlikely(ecl_t_of(module) != t_codeblock)) {
+ FEerror("UNLOAD-FOREIGN-MODULE: Argument is not a foreign module: ~S ",
+ 1, module);
+ }
+# ifdef ECL_THREADS
+ mp_get_lock(1, ecl_symbol_value(@'mp::+load-compile-lock+'));
+ ECL_UNWIND_PROTECT_BEGIN(ecl_process_env()) {
+# endif
+ if (ecl_likely(ecl_library_close(module))) output = ECL_T;
+# ifdef ECL_THREADS
+ (void)0; /* MSVC complains about missing ';' before '}' */
+ } ECL_UNWIND_PROTECT_EXIT {
+ mp_giveup_lock(ecl_symbol_value(@'mp::+load-compile-lock+'));
+ } ECL_UNWIND_PROTECT_END;
+# endif
+ @(return output)
+#endif
+}
+
+cl_object
si_find_foreign_symbol(cl_object var, cl_object module, cl_object type, cl_object size)
{
#if !defined(ENABLE_DLOPEN)
set_library_error(block);
}
-static void
+static int
dlclose_wrapper(cl_object block)
{
if (block->cblock.handle != NULL) {
FreeLibrary(block->cblock.handle);
#endif
block->cblock.handle = NULL;
+ return TRUE;
}
+ return FALSE;
}
static cl_object
return block->cblock.error;
}
-void
+bool
ecl_library_close(cl_object block) {
const cl_env_ptr the_env = ecl_process_env();
+ bool success = TRUE;
ECL_WITH_GLOBAL_LOCK_BEGIN(the_env) {
ecl_disable_interrupts();
- if (block->cblock.refs != ecl_make_fixnum(1)) {
+ /* is it ever a case? no matter how many times i call
+ load-foreign-module it seems that block->cblock.refs = 1 */
+ if (block->cblock.refs > ecl_make_fixnum(1)) {
block->cblock.refs = ecl_one_minus(block->cblock.refs);
block = ECL_NIL;
} else if (block->cblock.handle != NULL) {
- GC_call_with_alloc_lock(dlclose_wrapper, block);
+ success = GC_call_with_alloc_lock(dlclose_wrapper, block);
cl_core.libraries = ecl_remove_eq(block, cl_core.libraries);
- }
+ } else { /* block not loaded */
+ success = FALSE;
+ }
ecl_enable_interrupts();
} ECL_WITH_GLOBAL_LOCK_END;
if (block != ECL_NIL && block->cblock.self_destruct) {
unlink((char*)block->cblock.name->base_string.self);
}
}
+ return success;
}
void
{SYS_ "FREE-FOREIGN-DATA", SI_ORDINARY, si_free_foreign_data, 1, OBJNULL},
{SYS_ "MAKE-FOREIGN-DATA-FROM-ARRAY", SI_ORDINARY, si_make_foreign_data_from_array, 1, OBJNULL},
{SYS_ "LOAD-FOREIGN-MODULE", SI_ORDINARY, si_load_foreign_module, 1, OBJNULL},
+{SYS_ "UNLOAD-FOREIGN-MODULE", SI_ORDINARY, si_unload_foreign_module, 1, OBJNULL},
{SYS_ "NULL-POINTER-P", SI_ORDINARY, si_null_pointer_p, 1, OBJNULL},
{SYS_ "SIZE-OF-FOREIGN-ELT-TYPE", SI_ORDINARY, si_size_of_foreign_elt_type, 1, OBJNULL},
{SYS_ "ALIGNMENT-OF-FOREIGN-ELT-TYPE", SI_ORDINARY, si_alignment_of_foreign_elt_type, 1, OBJNULL},
{SYS_ "FREE-FOREIGN-DATA","si_free_foreign_data"},
{SYS_ "MAKE-FOREIGN-DATA-FROM-ARRAY","si_make_foreign_data_from_array"},
{SYS_ "LOAD-FOREIGN-MODULE","si_load_foreign_module"},
+{SYS_ "UNLOAD-FOREIGN-MODULE","si_unload_foreign_module"},
{SYS_ "NULL-POINTER-P","si_null_pointer_p"},
{SYS_ "SIZE-OF-FOREIGN-ELT-TYPE","si_size_of_foreign_elt_type"},
{SYS_ "ALIGNMENT-OF-FOREIGN-ELT-TYPE","si_alignment_of_foreign_elt_type"},
extern ECL_API cl_object ecl_library_open(cl_object filename, bool force_reload);
extern ECL_API void *ecl_library_symbol(cl_object block, const char *symbol, bool lock);
extern ECL_API cl_object ecl_library_error(cl_object block);
-extern ECL_API void ecl_library_close(cl_object block);
+extern ECL_API bool ecl_library_close(cl_object block);
extern ECL_API void ecl_library_close_all(void);
/* ffi/mmap.d */
extern ECL_API cl_object si_size_of_foreign_elt_type(cl_object tag);
extern ECL_API cl_object si_alignment_of_foreign_elt_type(cl_object tag);
extern ECL_API cl_object si_load_foreign_module(cl_object module);
+extern ECL_API cl_object si_unload_foreign_module(cl_object module);
extern ECL_API cl_object si_find_foreign_symbol(cl_object var, cl_object module, cl_object type, cl_object size);
extern ECL_API cl_object si_call_cfun(cl_narg, cl_object fun, cl_object return_type, cl_object arg_types, cl_object args, ...);
extern ECL_API cl_object si_make_dynamic_callback(cl_narg, cl_object fun, cl_object sym, cl_object return_type, cl_object arg_types, ...);