mirror of
https://github.com/janet-lang/janet
synced 2024-12-26 00:10:27 +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:
parent
e318170fea
commit
2e9f67f4e4
@ -2,10 +2,10 @@
|
||||
# An even more sophisticated macro wrapper could add
|
||||
# better doc strings, better parameter checking, etc.
|
||||
|
||||
(defn defnative-context
|
||||
(defn ffi-context
|
||||
"Load a dynamic library and set it as the context for following declarations"
|
||||
[location]
|
||||
(setdyn :raw-native (raw-native location)))
|
||||
(setdyn :raw-native (ffi/native location)))
|
||||
|
||||
(defmacro defnative
|
||||
"Declare a native binding"
|
||||
@ -16,12 +16,12 @@
|
||||
(def $sig (symbol name "-signature-"))
|
||||
(def $pointer (symbol name "-raw-pointer-"))
|
||||
~(upscope
|
||||
(def ,$pointer :private (as-macro ,assert (,native-lookup (,dyn :raw-native) ,raw-symbol)))
|
||||
(def ,$sig :private (,native-signature :default ,ret-type ,;signature-args))
|
||||
(def ,$pointer :private (as-macro ,assert (,ffi/lookup (,dyn :raw-native) ,raw-symbol)))
|
||||
(def ,$sig :private (,ffi/signature :default ,ret-type ,;signature-args))
|
||||
(defn ,name [,;defn-args]
|
||||
(,native-call ,$pointer ,$sig ,;defn-args))))
|
||||
(,ffi/call ,$pointer ,$sig ,;defn-args))))
|
||||
|
||||
(defnative-context "/usr/lib/libgtk-3.so")
|
||||
(ffi-context "/usr/lib/libgtk-3.so")
|
||||
|
||||
(defnative gtk-application-new :ptr [:ptr :uint])
|
||||
(defnative g-signal-connect-data :ulong [:ptr :ptr :ptr :ptr :ptr :int])
|
||||
@ -38,7 +38,7 @@
|
||||
# Limitation is that we cannot generate arbitrary closures to pass into apis.
|
||||
# However, any stubs we need we would simply need to compile ourselves, so
|
||||
# Janet includes a common stub out of the box.
|
||||
(def cb (native-trampoline :default))
|
||||
(def cb (ffi/trampoline :default))
|
||||
|
||||
(defn on-active
|
||||
[app]
|
||||
|
@ -1,72 +1,72 @@
|
||||
(def native-loc "ffitest/so.so")
|
||||
(def native-source-loc "ffitest/so.c")
|
||||
(def ffi/loc "ffitest/so.so")
|
||||
(def ffi/source-loc "ffitest/so.c")
|
||||
|
||||
(os/execute ["cc" native-source-loc "-shared" "-o" native-loc] :px)
|
||||
(def module (raw-native native-loc))
|
||||
(os/execute ["cc" ffi/source-loc "-shared" "-o" ffi/loc] :px)
|
||||
(def module (ffi/native ffi/loc))
|
||||
|
||||
(def int-fn-sig (native-signature :default :int :int :int))
|
||||
(def int-fn-pointer (native-lookup module "int_fn"))
|
||||
(def int-fn-sig (ffi/signature :default :int :int :int))
|
||||
(def int-fn-pointer (ffi/lookup module "int_fn"))
|
||||
(defn int-fn
|
||||
[x y]
|
||||
(native-call int-fn-pointer int-fn-sig x y))
|
||||
(ffi/call int-fn-pointer int-fn-sig x y))
|
||||
|
||||
(def double-fn-sig (native-signature :default :double :double :double :double))
|
||||
(def double-fn-pointer (native-lookup module "double_fn"))
|
||||
(def double-fn-sig (ffi/signature :default :double :double :double :double))
|
||||
(def double-fn-pointer (ffi/lookup module "double_fn"))
|
||||
(defn double-fn
|
||||
[x y z]
|
||||
(native-call double-fn-pointer double-fn-sig x y z))
|
||||
(ffi/call double-fn-pointer double-fn-sig x y z))
|
||||
|
||||
(def double-many-sig (native-signature :default :double :double :double :double :double :double :double))
|
||||
(def double-many-pointer (native-lookup module "double_many"))
|
||||
(def double-many-sig (ffi/signature :default :double :double :double :double :double :double :double))
|
||||
(def double-many-pointer (ffi/lookup module "double_many"))
|
||||
(defn double-many
|
||||
[x y z w a b]
|
||||
(native-call double-many-pointer double-many-sig x y z w a b))
|
||||
(ffi/call double-many-pointer double-many-sig x y z w a b))
|
||||
|
||||
(def double-lots-sig (native-signature :default :double
|
||||
(def double-lots-sig (ffi/signature :default :double
|
||||
:double :double :double :double :double
|
||||
:double :double :double :double :double))
|
||||
(def double-lots-pointer (native-lookup module "double_lots"))
|
||||
(def double-lots-pointer (ffi/lookup module "double_lots"))
|
||||
(defn double-lots
|
||||
[a b c d e f g h i j]
|
||||
(native-call double-lots-pointer double-lots-sig a b c d e f g h i j))
|
||||
(ffi/call double-lots-pointer double-lots-sig a b c d e f g h i j))
|
||||
|
||||
(def float-fn-sig (native-signature :default :double :float :float :float))
|
||||
(def float-fn-pointer (native-lookup module "float_fn"))
|
||||
(def float-fn-sig (ffi/signature :default :double :float :float :float))
|
||||
(def float-fn-pointer (ffi/lookup module "float_fn"))
|
||||
(defn float-fn
|
||||
[x y z]
|
||||
(native-call float-fn-pointer float-fn-sig x y z))
|
||||
(ffi/call float-fn-pointer float-fn-sig x y z))
|
||||
|
||||
(def intint-fn-sig (native-signature :default :int :double [:int :int]))
|
||||
(def intint-fn-pointer (native-lookup module "intint_fn"))
|
||||
(def intint-fn-sig (ffi/signature :default :int :double [:int :int]))
|
||||
(def intint-fn-pointer (ffi/lookup module "intint_fn"))
|
||||
(defn intint-fn
|
||||
[x ii]
|
||||
(native-call intint-fn-pointer intint-fn-sig x ii))
|
||||
(ffi/call intint-fn-pointer intint-fn-sig x ii))
|
||||
|
||||
(def return-struct-sig (native-signature :default [:int :int] :int))
|
||||
(def return-struct-pointer (native-lookup module "return_struct"))
|
||||
(def return-struct-sig (ffi/signature :default [:int :int] :int))
|
||||
(def return-struct-pointer (ffi/lookup module "return_struct"))
|
||||
(defn return-struct-fn
|
||||
[i]
|
||||
(native-call return-struct-pointer return-struct-sig i))
|
||||
(ffi/call return-struct-pointer return-struct-sig i))
|
||||
|
||||
(def intintint (native-struct :int :int :int))
|
||||
(def intintint-fn-sig (native-signature :default :int :double intintint))
|
||||
(def intintint-fn-pointer (native-lookup module "intintint_fn"))
|
||||
(def intintint (ffi/struct :int :int :int))
|
||||
(def intintint-fn-sig (ffi/signature :default :int :double intintint))
|
||||
(def intintint-fn-pointer (ffi/lookup module "intintint_fn"))
|
||||
(defn intintint-fn
|
||||
[x iii]
|
||||
(native-call intintint-fn-pointer intintint-fn-sig x iii))
|
||||
(ffi/call intintint-fn-pointer intintint-fn-sig x iii))
|
||||
|
||||
(def big (native-struct :s64 :s64 :s64))
|
||||
(def struct-big-fn-sig (native-signature :default big :int :double))
|
||||
(def struct-big-fn-pointer (native-lookup module "struct_big"))
|
||||
(def big (ffi/struct :s64 :s64 :s64))
|
||||
(def struct-big-fn-sig (ffi/signature :default big :int :double))
|
||||
(def struct-big-fn-pointer (ffi/lookup module "struct_big"))
|
||||
(defn struct-big-fn
|
||||
[i d]
|
||||
(native-call struct-big-fn-pointer struct-big-fn-sig i d))
|
||||
(ffi/call struct-big-fn-pointer struct-big-fn-sig i d))
|
||||
|
||||
(def void-fn-pointer (native-lookup module "void_fn"))
|
||||
(def void-fn-sig (native-signature :default :void))
|
||||
(def void-fn-pointer (ffi/lookup module "void_fn"))
|
||||
(def void-fn-sig (ffi/signature :default :void))
|
||||
(defn void-fn
|
||||
[]
|
||||
(native-call void-fn-pointer void-fn-sig))
|
||||
(ffi/call void-fn-pointer void-fn-sig))
|
||||
|
||||
#
|
||||
# Call functions
|
||||
@ -95,8 +95,8 @@
|
||||
|
||||
(defn check-round-trip
|
||||
[t value]
|
||||
(def buf (native-write t value))
|
||||
(def same-value (native-read t buf))
|
||||
(def buf (ffi/write t value))
|
||||
(def same-value (ffi/read t buf))
|
||||
(assert (deep= value same-value)
|
||||
(string/format "round trip %j (got %j)" value same-value)))
|
||||
|
||||
@ -121,7 +121,7 @@
|
||||
(check-round-trip :s32 0)
|
||||
(check-round-trip :s32 -1234567)
|
||||
|
||||
(def s (native-struct :s8 :s8 :s8 :float))
|
||||
(def s (ffi/struct :s8 :s8 :s8 :float))
|
||||
(check-round-trip s [1 3 5 123.5])
|
||||
(check-round-trip s [-1 -3 -5 -123.5])
|
||||
|
||||
|
@ -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),
|
||||
|
@ -194,6 +194,16 @@ static const JanetAbstractType janet_struct_type = {
|
||||
JANET_ATEND_GCMARK
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
Clib clib;
|
||||
int closed;
|
||||
} JanetAbstractNative;
|
||||
|
||||
static const JanetAbstractType janet_native_type = {
|
||||
"core/ffi-native",
|
||||
JANET_ATEND_NAME
|
||||
};
|
||||
|
||||
static JanetFFIType prim_type(JanetFFIPrimType pt) {
|
||||
JanetFFIType t;
|
||||
t.prim = pt;
|
||||
@ -352,7 +362,7 @@ static JanetFFIType decode_ffi_type(Janet x) {
|
||||
}
|
||||
|
||||
JANET_CORE_FN(cfun_ffi_struct,
|
||||
"(native-struct & types)",
|
||||
"(ffi/struct & types)",
|
||||
"Create a struct type descriptor that can be used to pass structs into native functions. ") {
|
||||
janet_arity(argc, 1, -1);
|
||||
return janet_wrap_abstract(build_struct_type(argc, argv));
|
||||
@ -555,7 +565,7 @@ static JanetFFIWordSpec sysv64_classify(JanetFFIType type) {
|
||||
#endif
|
||||
|
||||
JANET_CORE_FN(cfun_ffi_signature,
|
||||
"(native-signature calling-convention ret-type & arg-types)",
|
||||
"(ffi/signature calling-convention ret-type & arg-types)",
|
||||
"Create a function signature object that can be used to make calls "
|
||||
"with raw function pointers.") {
|
||||
janet_arity(argc, 2, -1);
|
||||
@ -989,7 +999,7 @@ static Janet janet_ffi_win64(JanetFFISignature *signature, void *function_pointe
|
||||
#endif
|
||||
|
||||
JANET_CORE_FN(cfun_ffi_call,
|
||||
"(native-call pointer signature & args)",
|
||||
"(ffi/call pointer signature & args)",
|
||||
"Call a raw pointer as a function pointer. The function signature specifies "
|
||||
"how Janet values in `args` are converted to native machine types.") {
|
||||
janet_arity(argc, 2, -1);
|
||||
@ -1011,7 +1021,7 @@ JANET_CORE_FN(cfun_ffi_call,
|
||||
}
|
||||
|
||||
JANET_CORE_FN(cfun_ffi_buffer_write,
|
||||
"(native-write ffi-type data &opt buffer)",
|
||||
"(ffi/write ffi-type data &opt buffer)",
|
||||
"Append a native tyep to a buffer such as it would appear in memory. This can be used "
|
||||
"to pass pointers to structs in the ffi, or send C/C++/native structs over the network "
|
||||
"or to files. Returns a modifed buffer or a new buffer if one is not supplied.") {
|
||||
@ -1028,9 +1038,9 @@ JANET_CORE_FN(cfun_ffi_buffer_write,
|
||||
|
||||
|
||||
JANET_CORE_FN(cfun_ffi_buffer_read,
|
||||
"(native-read ffi-type bytes &opt offset)",
|
||||
"(ffi/read ffi-type bytes &opt offset)",
|
||||
"Parse a native struct out of a buffer and convert it to normal Janet data structures. "
|
||||
"This function is the inverse of `native-write`. `bytes` can also be a raw pointer, although "
|
||||
"This function is the inverse of `ffi/write`. `bytes` can also be a raw pointer, although "
|
||||
"this is unsafe.") {
|
||||
janet_arity(argc, 2, 3);
|
||||
JanetFFIType type = decode_ffi_type(argv[0]);
|
||||
@ -1047,13 +1057,13 @@ JANET_CORE_FN(cfun_ffi_buffer_read,
|
||||
}
|
||||
|
||||
JANET_CORE_FN(cfun_ffi_get_callback_trampoline,
|
||||
"(native-trampoline cc)",
|
||||
"(ffi/trampoline cc)",
|
||||
"Get a native function pointer that can be used as a callback and passed to C libraries. "
|
||||
"This callback trampoline has the signature `void trampoline(void *ctx, void *userdata)` in "
|
||||
"the given calling convention. This is the only function signature supported. "
|
||||
"It is up to the programmer to ensure that the `userdata` argument contains a janet function "
|
||||
"the will be called with one argument, `ctx` which is an opaque pointer. This pointer can "
|
||||
"be further inspected with `native-read`.") {
|
||||
"be further inspected with `ffi/read`.") {
|
||||
janet_arity(argc, 0, 1);
|
||||
JanetFFICallingConvention cc = JANET_FFI_CC_DEFAULT;
|
||||
if (argc >= 1) cc = decode_ffi_cc(janet_getkeyword(argv, 0));
|
||||
@ -1070,14 +1080,59 @@ JANET_CORE_FN(cfun_ffi_get_callback_trampoline,
|
||||
}
|
||||
}
|
||||
|
||||
JANET_CORE_FN(janet_core_raw_native,
|
||||
"(ffi/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,
|
||||
"(ffi/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,
|
||||
"(ffi/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();
|
||||
}
|
||||
|
||||
void janet_lib_ffi(JanetTable *env) {
|
||||
JanetRegExt ffi_cfuns[] = {
|
||||
JANET_CORE_REG("native-signature", cfun_ffi_signature),
|
||||
JANET_CORE_REG("native-call", cfun_ffi_call),
|
||||
JANET_CORE_REG("native-struct", cfun_ffi_struct),
|
||||
JANET_CORE_REG("native-write", cfun_ffi_buffer_write),
|
||||
JANET_CORE_REG("native-read", cfun_ffi_buffer_read),
|
||||
JANET_CORE_REG("native-trampoline", cfun_ffi_get_callback_trampoline),
|
||||
JANET_CORE_REG("ffi/native", janet_core_raw_native),
|
||||
JANET_CORE_REG("ffi/lookup", janet_core_native_lookup),
|
||||
JANET_CORE_REG("ffi/close", janet_core_native_close),
|
||||
JANET_CORE_REG("ffi/signature", cfun_ffi_signature),
|
||||
JANET_CORE_REG("ffi/call", cfun_ffi_call),
|
||||
JANET_CORE_REG("ffi/struct", cfun_ffi_struct),
|
||||
JANET_CORE_REG("ffi/write", cfun_ffi_buffer_write),
|
||||
JANET_CORE_REG("ffi/read", cfun_ffi_buffer_read),
|
||||
JANET_CORE_REG("ffi/trampoline", cfun_ffi_get_callback_trampoline),
|
||||
JANET_REG_END
|
||||
};
|
||||
janet_core_cfuns_ext(env, NULL, ffi_cfuns);
|
||||
|
@ -884,6 +884,35 @@ int janet_cryptorand(uint8_t *out, size_t n) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Dynamic library loading */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#if defined(JANET_WINDOWS)
|
||||
static char error_clib_buf[256];
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Alloc function macro fills */
|
||||
void *(janet_malloc)(size_t size) {
|
||||
|
@ -127,6 +127,31 @@ int janet_gettime(struct timespec *spec);
|
||||
#define strdup(x) _strdup(x)
|
||||
#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))
|
||||
char *error_clib(void);
|
||||
#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
|
||||
char *get_processed_name(const char *name);
|
||||
|
||||
#define RETRY_EINTR(RC, CALL) do { (RC) = CALL; } while((RC) < 0 && errno == EINTR)
|
||||
|
||||
/* Initialize builtin libraries */
|
||||
|
Loading…
Reference in New Issue
Block a user