mirror of
https://github.com/janet-lang/janet
synced 2025-11-18 00:05:13 +00:00
Change all "native-*" to ffi/. Move new dll loading funcs.
native-close, raw-native and native-lookup have become ffi/close, ffi/native, and ffi/lookup instead. The new ffi module will be useful for any architecture even if we don't support making calls to certain functions. We can simple add a do-nothing calling convetion that panics on call. ffi/read and ffi/write are useful in their own right.
This commit is contained in:
@@ -42,64 +42,6 @@ extern size_t janet_core_image_size;
|
||||
#define JDOC(x) NULL
|
||||
#endif
|
||||
|
||||
/* Use LoadLibrary on windows or dlopen on posix to load dynamic libaries
|
||||
* with native code. */
|
||||
#if defined(JANET_NO_DYNAMIC_MODULES)
|
||||
typedef int Clib;
|
||||
#define load_clib(name) ((void) name, 0)
|
||||
#define symbol_clib(lib, sym) ((void) lib, (void) sym, NULL)
|
||||
#define error_clib() "dynamic libraries not supported"
|
||||
#define free_clib(c) ((void) (c), 0)
|
||||
#elif defined(JANET_WINDOWS)
|
||||
#include <windows.h>
|
||||
typedef HINSTANCE Clib;
|
||||
#define load_clib(name) LoadLibrary((name))
|
||||
#define free_clib(c) FreeLibrary((c))
|
||||
#define symbol_clib(lib, sym) GetProcAddress((lib), (sym))
|
||||
static char error_clib_buf[256];
|
||||
static char *error_clib(void) {
|
||||
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
error_clib_buf, sizeof(error_clib_buf), NULL);
|
||||
error_clib_buf[strlen(error_clib_buf) - 1] = '\0';
|
||||
return error_clib_buf;
|
||||
}
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
typedef void *Clib;
|
||||
#define load_clib(name) dlopen((name), RTLD_NOW)
|
||||
#define free_clib(lib) dlclose((lib))
|
||||
#define symbol_clib(lib, sym) dlsym((lib), (sym))
|
||||
#define error_clib() dlerror()
|
||||
#endif
|
||||
|
||||
static char *get_processed_name(const char *name) {
|
||||
if (name[0] == '.') return (char *) name;
|
||||
const char *c;
|
||||
for (c = name; *c; c++) {
|
||||
if (*c == '/') return (char *) name;
|
||||
}
|
||||
size_t l = (size_t)(c - name);
|
||||
char *ret = janet_malloc(l + 3);
|
||||
if (NULL == ret) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
ret[0] = '.';
|
||||
ret[1] = '/';
|
||||
memcpy(ret + 2, name, l + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Clib clib;
|
||||
int closed;
|
||||
} JanetAbstractNative;
|
||||
|
||||
static const JanetAbstractType janet_native_type = {
|
||||
"core/native",
|
||||
JANET_ATEND_NAME
|
||||
};
|
||||
|
||||
JanetModule janet_native(const char *name, const uint8_t **error) {
|
||||
char *processed_name = get_processed_name(name);
|
||||
Clib lib = load_clib(processed_name);
|
||||
@@ -350,48 +292,6 @@ JANET_CORE_FN(janet_core_native,
|
||||
return janet_wrap_table(env);
|
||||
}
|
||||
|
||||
JANET_CORE_FN(janet_core_raw_native,
|
||||
"(raw-native path)",
|
||||
"Load a shared object or dll from the given path, and do not extract"
|
||||
" or run any code from it. This is different than `native`, which will "
|
||||
"run initialization code to get a module table. Returns a `core/native`.") {
|
||||
janet_fixarity(argc, 1);
|
||||
const char *path = janet_getcstring(argv, 0);
|
||||
char *processed_name = get_processed_name(path);
|
||||
Clib lib = load_clib(processed_name);
|
||||
if (path != processed_name) janet_free(processed_name);
|
||||
if (!lib) janet_panic(error_clib());
|
||||
JanetAbstractNative *anative = janet_abstract(&janet_native_type, sizeof(JanetAbstractNative));
|
||||
anative->clib = lib;
|
||||
anative->closed = 0;
|
||||
return janet_wrap_abstract(anative);
|
||||
}
|
||||
|
||||
JANET_CORE_FN(janet_core_native_lookup,
|
||||
"(native-lookup native symbol-name)",
|
||||
"Lookup a symbol from a native object. All symbol lookups will return a raw pointer "
|
||||
"if the symbol is found, else nil.") {
|
||||
janet_fixarity(argc, 2);
|
||||
JanetAbstractNative *anative = janet_getabstract(argv, 0, &janet_native_type);
|
||||
const char *sym = janet_getcstring(argv, 1);
|
||||
if (anative->closed) janet_panic("native object already closed");
|
||||
void *value = symbol_clib(anative->clib, sym);
|
||||
if (NULL == value) return janet_wrap_nil();
|
||||
return janet_wrap_pointer(value);
|
||||
}
|
||||
|
||||
JANET_CORE_FN(janet_core_native_close,
|
||||
"(native-close native)",
|
||||
"Free a native object. Dereferencing pointers to symbols in the object will have undefined "
|
||||
"behavior after freeing.") {
|
||||
janet_fixarity(argc, 1);
|
||||
JanetAbstractNative *anative = janet_getabstract(argv, 0, &janet_native_type);
|
||||
if (anative->closed) janet_panic("native object already closed");
|
||||
anative->closed = 1;
|
||||
free_clib(anative->clib);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
JANET_CORE_FN(janet_core_describe,
|
||||
"(describe x)",
|
||||
"Returns a string that is a human-readable description of `x`. "
|
||||
@@ -1011,9 +911,6 @@ static const uint32_t cmp_asm[] = {
|
||||
static void janet_load_libs(JanetTable *env) {
|
||||
JanetRegExt corelib_cfuns[] = {
|
||||
JANET_CORE_REG("native", janet_core_native),
|
||||
JANET_CORE_REG("raw-native", janet_core_raw_native),
|
||||
JANET_CORE_REG("native-lookup", janet_core_native_lookup),
|
||||
JANET_CORE_REG("native-close", janet_core_native_close),
|
||||
JANET_CORE_REG("describe", janet_core_describe),
|
||||
JANET_CORE_REG("string", janet_core_string),
|
||||
JANET_CORE_REG("symbol", janet_core_symbol),
|
||||
|
||||
Reference in New Issue
Block a user