Refactor dln_load into dln_open and dln_sym

Refactor dln_load into dln_open and dln_sym to simplify the code for
Windows and platforms that have dlopen.
This commit is contained in:
Peter Zhu 2022-01-19 09:00:33 -05:00
Родитель 374904b25f
Коммит 5c4734d1ef
1 изменённых файлов: 82 добавлений и 77 удалений

159
dln.c
Просмотреть файл

@ -279,28 +279,19 @@ dln_incompatible_library_p(void *handle)
COMPILER_WARNING_POP COMPILER_WARNING_POP
#endif #endif
void* #if defined(_WIN32) || defined(USE_DLN_DLOPEN)
dln_load(const char *file) static void *
dln_open(const char *file)
{ {
#if (defined _WIN32 || defined USE_DLN_DLOPEN) && defined RUBY_EXPORT
static const char incompatible[] = "incompatible library version"; static const char incompatible[] = "incompatible library version";
#endif const char *error = NULL;
#if defined _WIN32 || defined USE_DLN_DLOPEN void *handle;
const char *error = 0;
#endif
#if defined _WIN32 #if defined(_WIN32)
HINSTANCE handle;
WCHAR *winfile;
char message[1024]; char message[1024];
void (*init_fct)(void);
char *buf;
/* Load the file as an object one */
init_funcname(&buf, file);
/* Convert the file path to wide char */ /* Convert the file path to wide char */
winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL); WCHAR *winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
if (!winfile) { if (!winfile) {
dln_memerror(); dln_memerror();
} }
@ -314,82 +305,104 @@ dln_load(const char *file)
goto failed; goto failed;
} }
#if defined _WIN32 && defined RUBY_EXPORT # if defined(RUBY_EXPORT)
if (!rb_w32_check_imported(handle, rb_libruby_handle())) { if (!rb_w32_check_imported(handle, rb_libruby_handle())) {
FreeLibrary(handle); FreeLibrary(handle);
error = incompatible; error = incompatible;
goto failed; goto failed;
} }
#endif # endif
if ((init_fct = (void(*)(void))GetProcAddress(handle, buf)) == NULL) { #elif defined(USE_DLN_DLOPEN)
dln_loaderror("%s - %s\n%s", dln_strerror(), buf, file);
# ifndef RTLD_LAZY
# define RTLD_LAZY 1
# endif
# ifdef __INTERIX
# undef RTLD_GLOBAL
# endif
# ifndef RTLD_GLOBAL
# define RTLD_GLOBAL 0
# endif
/* Load file */
handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL);
if (handle == NULL) {
error = dln_strerror();
goto failed;
} }
/* Call the init code */ # if defined(RUBY_EXPORT)
(*init_fct)();
return handle;
#else
char *buf;
/* Load the file as an object one */
init_funcname(&buf, file);
translit_separator(file);
#ifdef USE_DLN_DLOPEN
#define DLN_DEFINED
{
void *handle;
void (*init_fct)(void);
#ifndef RTLD_LAZY
# define RTLD_LAZY 1
#endif
#ifdef __INTERIX
# undef RTLD_GLOBAL
#endif
#ifndef RTLD_GLOBAL
# define RTLD_GLOBAL 0
#endif
/* Load file */
if ((handle = (void*)dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
error = dln_strerror();
goto failed;
}
# if defined RUBY_EXPORT
{ {
if (dln_incompatible_library_p(handle)) { if (dln_incompatible_library_p(handle)) {
# if defined(__APPLE__) && \
# if defined __APPLE__ && \
defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \ defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11) (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11)
/* dlclose() segfaults */ /* dlclose() segfaults */
rb_fatal("%s - %s", incompatible, file); rb_fatal("%s - %s", incompatible, file);
# else # else
dlclose(handle); dlclose(handle);
error = incompatible; error = incompatible;
goto failed; goto failed;
# endif # endif
} }
} }
# endif # endif
#endif
init_fct = (void(*)(void))(VALUE)dlsym(handle, buf); return handle;
if (init_fct == NULL) {
const size_t errlen = strlen(error = dln_strerror()) + 1;
error = memcpy(ALLOCA_N(char, errlen), error, errlen);
dlclose(handle);
goto failed;
}
/* Call the init code */
(*init_fct)();
return handle; failed:
dln_loaderror("%s - %s", error, file);
}
static void *
dln_sym(void *handle, const char *symbol)
{
void *func;
const char *error;
#if defined(_WIN32)
char message[1024];
func = GetProcAddress(handle, symbol);
if (func == NULL) {
error = dln_strerror();
goto failed;
} }
#endif /* USE_DLN_DLOPEN */
#if defined(_AIX) #elif defined(USE_DLN_DLOPEN)
#define DLN_DEFINED func = dlsym(handle, symbol);
if (func == NULL) {
const size_t errlen = strlen(error = dln_strerror()) + 1;
error = memcpy(ALLOCA_N(char, errlen), error, errlen);
goto failed;
}
#endif
return func;
failed:
dln_loaderror("%s - %s", error, symbol);
}
#endif
void *
dln_load(const char *file)
{
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
void *handle = dln_open(file);
char *init_fct_name;
init_funcname(&init_fct_name, file);
void (*init_fct)(void) = (void(*)(void))dln_sym(handle, init_fct_name);
/* Call the init code */
(*init_fct)();
return handle;
#elif defined(_AIX)
{ {
void (*init_fct)(void); void (*init_fct)(void);
@ -403,17 +416,9 @@ dln_load(const char *file)
(*init_fct)(); (*init_fct)();
return (void*)init_fct; return (void*)init_fct;
} }
#endif /* _AIX */ #else
#ifndef DLN_DEFINED
dln_notimplement(); dln_notimplement();
#endif #endif
#endif
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
failed:
dln_loaderror("%s - %s", error, file);
#endif
return 0; /* dummy return */ return 0; /* dummy return */
} }