get c symbol

This commit is contained in:
2025-11-28 13:07:36 -06:00
parent b577e889a1
commit d361cb0555
3 changed files with 169 additions and 31 deletions

View File

@@ -12,7 +12,7 @@ var dylib_ext = hidden.dylib_ext
var load_internal = hidden.load_internal var load_internal = hidden.load_internal
function use_embed(name) { function use_embed(name) {
return load_internal(name) return load_internal(`js_${name}_use`)
} }
var actor_mod = use_embed('actor') var actor_mod = use_embed('actor')
@@ -20,6 +20,7 @@ var wota = use_embed('wota')
var nota = use_embed('nota') var nota = use_embed('nota')
var enet = use_embed('enet') var enet = use_embed('enet')
var fd = use_embed('fd') var fd = use_embed('fd')
var os = use_embed('os')
var console_mod = use_embed('console') var console_mod = use_embed('console')
var ENETSERVICE = 0.1 var ENETSERVICE = 0.1
@@ -30,6 +31,41 @@ var ACTOR_EXT = '.ce'
globalThis.pi = 3.1415926535897932 globalThis.pi = 3.1415926535897932
var open_dl = {}
function get_import_package(name) {
var parts = name.split('/')
if (parts.length > 1)
return parts[0]
return null
}
function get_import_dl(name) {
var pkg = get_import_package(name)
if (!pkg) return null
if (open_dl[pkg]) return open_dl[pkg]
var dlpath = `.cell/modules/${pkg}/${pkg}${dylib_ext}`
var dl = os.dylib_open(dlpath)
if (dl) {
open_dl[pkg] = dl
return dl
}
return null
}
// tries to load a C symbol from either a dynamic library or within the executable
// an import 'debug/profile' can either be in a dynamic library debug.so or within the executable
function get_c_symbol(name) {
var dl = get_import_dl(name)
var symname = `js_${name.replace('/', '_')}_use`
if (dl)
return os.dylib_symbol(dl, symname)
else
return load_internal(symname)
}
function caller_data(depth = 0) function caller_data(depth = 0)
{ {
var file = "nofile" var file = "nofile"
@@ -78,13 +114,7 @@ log.system = function(msg) {
log.console(msg) log.console(msg)
} }
log.console(fd.getcwd())
log.console(cell.args.program)
var shop_path = '.cell' var shop_path = '.cell'
var mod_path = '.cell/modules/'
if (!fd.stat('.cell').isDirectory) { if (!fd.stat('.cell').isDirectory) {
log.console("No cell directory found. Make one.\n"); log.console("No cell directory found. Make one.\n");
@@ -358,9 +388,10 @@ globalThis.use = function use(file, ...args) {
var compiledPath = get_compiled_path(resolved) var compiledPath = get_compiled_path(resolved)
var useCompiled = false var useCompiled = false
if (is_file(compiledPath)) { // Always compile from source - never use precompiled for core modules
useCompiled = true // if (is_file(compiledPath)) {
} // useCompiled = true
// }
var fn var fn
if (useCompiled) { if (useCompiled) {
@@ -428,9 +459,10 @@ globalThis.use = function use(file, ...args) {
var srcStat = fd.stat(path) var srcStat = fd.stat(path)
var compiledStat = fd.stat(compiledPath) var compiledStat = fd.stat(compiledPath)
if (srcStat && srcStat.isFile && compiledStat && compiledStat.isFile && compiledStat.mtime > srcStat.mtime) { // Always compile from source - never use precompiled for regular modules
useCompiled = true // if (srcStat && srcStat.isFile && compiledStat && compiledStat.isFile && compiledStat.mtime > srcStat.mtime) {
} // useCompiled = true
// }
var fn var fn
var mod_name = path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.')) var mod_name = path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.'))
@@ -1078,19 +1110,20 @@ var startfn
var compiledPath = get_compiled_path(resolved_prog) var compiledPath = get_compiled_path(resolved_prog)
var useCompiled = false var useCompiled = false
if (resolved_prog.isCore) { // Always compile from source - never use precompiled for main program
// For core, we check if we have a compiled version, else we compile it // if (resolved_prog.isCore) {
if (is_file(compiledPath)) { // // For core, we check if we have a compiled version, else we compile it
useCompiled = true // if (is_file(compiledPath)) {
} // useCompiled = true
} else { // }
// For local/modules, check timestamps // } else {
var srcStat = fd.stat(prog) // // For local/modules, check timestamps
var compiledStat = fd.stat(compiledPath) // var srcStat = fd.stat(prog)
if (srcStat && srcStat.isFile && compiledStat && compiledStat.isFile && compiledStat.mtime > srcStat.mtime) { // var compiledStat = fd.stat(compiledPath)
useCompiled = true // if (srcStat && srcStat.isFile && compiledStat && compiledStat.isFile && compiledStat.mtime > srcStat.mtime) {
} // useCompiled = true
} // }
// }
if (useCompiled) { if (useCompiled) {
var compiledBlob = fd.slurp(compiledPath) var compiledBlob = fd.slurp(compiledPath)

View File

@@ -16,12 +16,31 @@
#else #else
#include <unistd.h> #include <unistd.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <dlfcn.h>
#ifdef __linux__ #ifdef __linux__
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
#include <sys/resource.h> #include <sys/resource.h>
#endif #endif
#endif #endif
static JSClassID js_dylib_class_id;
static void js_dylib_finalizer(JSRuntime *rt, JSValue val) {
void *handle = JS_GetOpaque(val, js_dylib_class_id);
if (handle) {
#ifdef _WIN32
FreeLibrary((HMODULE)handle);
#else
dlclose(handle);
#endif
}
}
static JSClassDef js_dylib_class = {
"dylib",
.finalizer = js_dylib_finalizer,
};
JSC_CCALL(os_now, return number2js(js, (double)SDL_GetTicksNS()/1000000000.0)) JSC_CCALL(os_now, return number2js(js, (double)SDL_GetTicksNS()/1000000000.0))
JSC_CCALL(os_sleep, JSC_CCALL(os_sleep,
@@ -279,6 +298,91 @@ JSC_SCALL(os_exit,
exit(0); exit(0);
) )
static JSValue js_os_dylib_open(JSContext *js, JSValue self, int argc, JSValue *argv)
{
if (argc < 1) {
return JS_ThrowTypeError(js, "dylib_open requires a path argument");
}
const char *path = JS_ToCString(js, argv[0]);
if (!path) {
return JS_ThrowTypeError(js, "path must be a string");
}
void *handle;
#ifdef _WIN32
handle = LoadLibraryA(path);
#else
handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
#endif
JS_FreeCString(js, path);
if (!handle) {
const char *error_msg = "Could not load library";
#ifndef _WIN32
const char *dl_error = dlerror();
if (dl_error) {
error_msg = dl_error;
}
#endif
return JS_ThrowReferenceError(js, "Failed to load library: %s", error_msg);
}
JSValue dylib_obj = JS_NewObjectClass(js, js_dylib_class_id);
if (JS_IsException(dylib_obj)) {
#ifdef _WIN32
FreeLibrary((HMODULE)handle);
#else
dlclose(handle);
#endif
return dylib_obj;
}
JS_SetOpaque(dylib_obj, handle);
return dylib_obj;
}
static JSValue js_os_dylib_symbol(JSContext *js, JSValue self, int argc, JSValue *argv)
{
if (argc < 2) {
return JS_ThrowTypeError(js, "dylib_symbol requires dylib object and symbol name");
}
void *handle = JS_GetOpaque(argv[0], js_dylib_class_id);
if (!handle) {
return JS_ThrowTypeError(js, "First argument must be a dylib object");
}
const char *symbol_name = JS_ToCString(js, argv[1]);
if (!symbol_name) {
return JS_ThrowTypeError(js, "symbol name must be a string");
}
void *symbol;
#ifdef _WIN32
symbol = GetProcAddress((HMODULE)handle, symbol_name);
#else
symbol = dlsym(handle, symbol_name);
#endif
JS_FreeCString(js, symbol_name);
if (!symbol) {
const char *error_msg = "Symbol not found";
#ifndef _WIN32
const char *dl_error = dlerror();
if (dl_error) {
error_msg = dl_error;
}
#endif
return JS_ThrowReferenceError(js, "Failed to get symbol: %s", error_msg);
}
// Return the symbol as a pointer value
return JS_NewInt64(js, (int64_t)(uintptr_t)symbol);
}
static const JSCFunctionListEntry js_os_funcs[] = { static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, platform, 0), MIST_FUNC_DEF(os, platform, 0),
MIST_FUNC_DEF(os, arch, 0), MIST_FUNC_DEF(os, arch, 0),
@@ -294,9 +398,14 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, frame, 0), MIST_FUNC_DEF(os, frame, 0),
MIST_FUNC_DEF(os, system, 1), MIST_FUNC_DEF(os, system, 1),
MIST_FUNC_DEF(os, exit, 0), MIST_FUNC_DEF(os, exit, 0),
MIST_FUNC_DEF(os, dylib_open, 1),
MIST_FUNC_DEF(os, dylib_symbol, 2),
}; };
JSValue js_os_use(JSContext *js) { JSValue js_os_use(JSContext *js) {
JS_NewClassID(&js_dylib_class_id);
JS_NewClass(JS_GetRuntime(js), js_dylib_class_id, &js_dylib_class);
JSValue mod = JS_NewObject(js); JSValue mod = JS_NewObject(js);
JS_SetPropertyFunctionList(js,mod,js_os_funcs,countof(js_os_funcs)); JS_SetPropertyFunctionList(js,mod,js_os_funcs,countof(js_os_funcs));
return mod; return mod;

View File

@@ -283,17 +283,13 @@ JSC_CCALL(os_use_dyn,
return fn(js); return fn(js);
) )
JSC_SCALL(os_load_internal, JSC_SCALL(os_load_internal,
void *handle = get_main_module_handle(); void *handle = get_main_module_handle();
if (!handle) { if (!handle) {
return JS_ThrowReferenceError(js, "Could not get main module handle"); return JS_ThrowReferenceError(js, "Could not get main module handle");
} }
char func_name[256]; JSValue (*js_use)(JSContext*) = get_symbol(handle, str);
snprintf(func_name, sizeof(func_name), "js_%s_use", str);
JSValue (*js_use)(JSContext*) = get_symbol(handle, func_name);
if (!js_use) { if (!js_use) {
// Try without "js_" prefix or other variations if needed, but standard is js_<name>_use // Try without "js_" prefix or other variations if needed, but standard is js_<name>_use