Skip to content

Instantly share code, notes, and snippets.

@metab0t
Created November 16, 2020 12:34
Show Gist options
  • Save metab0t/f0cc1a908a557757c686ad79b3bddb32 to your computer and use it in GitHub Desktop.
Save metab0t/f0cc1a908a557757c686ad79b3bddb32 to your computer and use it in GitHub Desktop.
Test Julia dlopen function
#include <windows.h>
#include <direct.h>
#include <assert.h>
#include <stdio.h>
#define _OS_WINDOWS_
int isabspath(const char *in) {
#ifdef _OS_WINDOWS_
char c0 = in[0];
if (c0 == '/' || c0 == '\\') {
return 1; // absolute path relative to %CD% (current drive), or UNC
} else if (c0 && in[1] == ':') {
char c2 = in[2];
return c2 == '/' || c2 == '\\'; // absolute path with drive name
}
#else
if (in[0] == '/')
return 1; // absolute path
#endif
return 0; // relative path
}
#if defined(__APPLE__)
static char const *const extensions[] = {"", ".dylib"};
#elif defined(_OS_WINDOWS_)
static char const *const extensions[] = {"", ".dll"};
extern volatile int needsSymRefreshModuleList;
#else
static char const *const extensions[] = {"", ".so"};
#endif
#define N_EXTENSIONS (sizeof(extensions) / sizeof(char *))
static int endswith_extension(const char *path) {
if (!path)
return 0;
size_t len = strlen(path);
// Skip the first one since it is empty
for (size_t i = 1; i < N_EXTENSIONS; i++) {
const char *ext = extensions[i];
size_t extlen = strlen(ext);
if (len < extlen)
return 0;
// Skip version extensions if present
size_t j = len - 1;
while (j > 0) {
if (path[j] == '.' || (path[j] >= '0' && path[j] <= '9'))
j--;
else
break;
}
if ((j == len - 1 || path[j + 1] == '.') &&
memcmp(ext, path + j - extlen + 1, extlen) == 0) {
return 1;
}
}
return 0;
}
#define PATHBUF 4096
#define JL_RTLD(flags, FLAG) (flags & JL_RTLD_##FLAG ? RTLD_##FLAG : 0)
#ifdef _OS_WINDOWS_
static void win32_formatmessage(DWORD code, char *reason, int len) {
DWORD res;
LPWSTR errmsg;
res = FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL, code, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPWSTR)&errmsg, 0, NULL);
if (!res && (GetLastError() == ERROR_MUI_FILE_NOT_FOUND ||
GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND)) {
res = FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL, code, 0, (LPWSTR)&errmsg, 0, NULL);
}
res = WideCharToMultiByte(CP_UTF8, 0, errmsg, -1, reason, len, NULL, NULL);
assert(res > 0 || GetLastError() == ERROR_INSUFFICIENT_BUFFER);
reason[len - 1] = '\0';
LocalFree(errmsg);
}
#endif
void *jl_dlopen(const char *filename, unsigned flags) {
#if defined(_OS_WINDOWS_)
size_t len = MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
if (!len)
return NULL;
WCHAR *wfilename = (WCHAR *)alloca(len * sizeof(WCHAR));
if (!MultiByteToWideChar(CP_UTF8, 0, filename, -1, wfilename, len))
return NULL;
HANDLE lib = LoadLibraryExW(wfilename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
// if (lib)
// needsSymRefreshModuleList = 1;
return lib;
#else
dlerror(); /* Reset error status. */
return dlopen(filename, (flags & JL_RTLD_NOW ? RTLD_NOW : RTLD_LAZY) |
JL_RTLD(flags, LOCAL) | JL_RTLD(flags, GLOBAL)
#ifdef RTLD_NODELETE
| JL_RTLD(flags, NODELETE)
#endif
#ifdef RTLD_NOLOAD
| JL_RTLD(flags, NOLOAD)
#endif
#if defined(RTLD_DEEPBIND) && \
!(defined(JL_ASAN_ENABLED) || defined(JL_TSAN_ENABLED) || \
defined(JL_MSAN_ENABLED))
| JL_RTLD(flags, DEEPBIND)
#endif
#ifdef RTLD_FIRST
| JL_RTLD(flags, FIRST)
#endif
);
#endif
}
void *jl_load_dynamic_library(const char *modname, unsigned flags,
int throw_err) {
char path[PATHBUF], relocated[PATHBUF];
int i;
#ifdef _OS_WINDOWS_
int err;
#endif
void *handle;
int abspath;
// number of extensions to try — if modname already ends with the
// standard extension, then we don't try adding additional extensions
int n_extensions = endswith_extension(modname) ? 1 : N_EXTENSIONS;
abspath = isabspath(modname);
assert(abspath != 0);
// now fall back and look in default library paths, for all extensions
for (i = 0; i < n_extensions; i++) {
const char *ext = extensions[i];
path[0] = '\0';
snprintf(path, PATHBUF, "%s%s", modname, ext);
handle = jl_dlopen(path, flags);
if (handle)
goto done;
#ifdef _OS_WINDOWS_
err = GetLastError();
break; // LoadLibrary already tested the rest
#endif
}
notfound:
if (throw_err) {
#ifdef _OS_WINDOWS_
char reason[256];
win32_formatmessage(err, reason, sizeof(reason));
#else
const char *reason = dlerror();
#endif
#ifndef __clang_analyzer__
// Hide the error throwing from the analyser since there isn't a way to
// express "safepoint only when throwing error" currently.
printf("could not load library \"%s\"\n%s", modname, reason);
#endif
}
handle = NULL;
done:
return handle;
}
int main(int argc, char const *argv[]) {
// write your path of dll
const char libname[] = "C:\\msys64\\home\\meta\\dist\\bin\\libcoinmumps-2.dll";
int flags = 0;
int throw_error = 1;
void *handle = jl_load_dynamic_library(libname, flags, throw_error);
if (handle) {
printf("successful\n");
}
done:
return 0;
}
function dlopen(s::AbstractString, flags::Integer=0; throw_error::Bool=true)
ret = ccall(:jl_load_dynamic_library, Ptr{Cvoid}, (Cstring, UInt32, Cint), s, flags, Cint(throw_error))
if ret == C_NULL
return nothing
end
return ret
end
libname = "C:\\msys64\\home\\meta\\dist\\bin\\libcoinmumps-2.dll"
dlopen(libname)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment