BTW, i made a similar design decision in Guile 1.4.x (see below), which now i regret, so that's why i comment: to selfishly keep you away from my regrets so that you can find your own. :-D
[cc trimmed] ________________________________________________________ SCM_DEFINE (scm_dynamic_link, "dynamic-link", 1, 0, 0, (SCM name), doc: /*********** Open the dynamic library file @var{name} and return its @dfn{library handle}, suitable for passing to the following functions. As a special case, if @var{name} is @code{#f}, the returned handle is for the Guile executable itself. */) { #define FUNC_NAME s_scm_dynamic_link const char *fname = NULL; lt_dladvise advise; lt_dlhandle handle; if (SCM_NFALSEP (name)) { SCM_COERCE_SUBSTR (name); SCM_VALIDATE_ROSTRING_COPY (1, name, fname); } NOINTS (); ZHOPEFULLY (lt_dladvise_init (&advise)); ZHOPEFULLY (lt_dladvise_global (&advise)); if (!fname || '/' != fname[0]) ZHOPEFULLY (lt_dladvise_ext (&advise)); handle = lt_dlopenadvise (fname, advise); lt_dladvise_destroy (&advise); HOPEFULLY (handle); INTSOK (); SCM_RETURN_NEWSMOB2 (tc, SCM_UNPACK (name), handle); #undef FUNC_NAME }