#include "loader.h" #include #include #include RavaNativeRegistry_t* rava_native_registry_create(void) { RavaNativeRegistry_t *registry = calloc(1, sizeof(RavaNativeRegistry_t)); if (!registry) return NULL; registry->library_count = 0; registry->cache_count = 0; return registry; } void rava_native_registry_destroy(RavaNativeRegistry_t *registry) { if (!registry) return; for (size_t i = 0; i < registry->library_count; i++) { rava_native_library_unload(registry, registry->libraries[i]); } free(registry); } static uint32_t _hash_method_name(const char *class_name, const char *method_name) { uint32_t hash = 5381; for (const char *p = class_name; *p; p++) { hash = ((hash << 5) + hash) + (uint32_t)*p; } hash = ((hash << 5) + hash) + '.'; for (const char *p = method_name; *p; p++) { hash = ((hash << 5) + hash) + (uint32_t)*p; } return hash % RAVA_MAX_NATIVE_METHODS; } RavaNativeLibrary_t* rava_native_library_load(RavaNativeRegistry_t *registry, const char *path) { if (!registry || !path) return NULL; if (registry->library_count >= RAVA_MAX_NATIVE_LIBRARIES) return NULL; void *handle = dlopen(path, RTLD_NOW | RTLD_LOCAL); if (!handle) { return NULL; } RavaNativeLibrary_t *lib = calloc(1, sizeof(RavaNativeLibrary_t)); if (!lib) { dlclose(handle); return NULL; } lib->path = strdup(path); lib->handle = handle; lib->method_count = 0; lib->method_capacity = 16; lib->methods = calloc(lib->method_capacity, sizeof(RavaNativeMethod_t)); const char *name_start = strrchr(path, '/'); if (name_start) { name_start++; } else { name_start = path; } if (strncmp(name_start, "lib", 3) == 0) { name_start += 3; } size_t name_len = strlen(name_start); if (name_len > 3 && strcmp(name_start + name_len - 3, ".so") == 0) { lib->name = strndup(name_start, name_len - 3); } else { lib->name = strdup(name_start); } RavaLibraryRegisterFn register_fn = (RavaLibraryRegisterFn)dlsym(handle, RAVA_LIBRARY_REGISTER_SYMBOL); if (register_fn) { register_fn(registry); } registry->libraries[registry->library_count++] = lib; return lib; } void rava_native_library_unload(RavaNativeRegistry_t *registry, RavaNativeLibrary_t *lib) { if (!registry || !lib) return; for (size_t i = 0; i < lib->method_count; i++) { free(lib->methods[i].class_name); free(lib->methods[i].method_name); } free(lib->methods); if (lib->handle) { dlclose(lib->handle); } free(lib->name); free(lib->path); free(lib); } bool rava_native_register_method(RavaNativeRegistry_t *registry, const char *class_name, const char *method_name, RavaNativeType_e return_type, RavaNativeType_e *param_types, size_t param_count, RavaNativeFunction_fn function, void *user_data) { if (!registry || !class_name || !method_name || !function) return false; if (param_count > RAVA_MAX_METHOD_PARAMS) return false; if (registry->cache_count >= RAVA_MAX_NATIVE_METHODS) return false; RavaNativeMethod_t *method = calloc(1, sizeof(RavaNativeMethod_t)); if (!method) return false; method->class_name = strdup(class_name); method->method_name = strdup(method_name); method->return_type = return_type; method->param_count = param_count; method->function = function; method->user_data = user_data; for (size_t i = 0; i < param_count; i++) { method->param_types[i] = param_types[i]; } uint32_t hash = _hash_method_name(class_name, method_name); while (registry->method_cache[hash] != NULL) { hash = (hash + 1) % RAVA_MAX_NATIVE_METHODS; } registry->method_cache[hash] = method; registry->cache_count++; return true; } RavaNativeMethod_t* rava_native_find_method(RavaNativeRegistry_t *registry, const char *class_name, const char *method_name) { if (!registry || !class_name || !method_name) return NULL; uint32_t hash = _hash_method_name(class_name, method_name); uint32_t start = hash; do { RavaNativeMethod_t *method = registry->method_cache[hash]; if (!method) return NULL; if (strcmp(method->class_name, class_name) == 0 && strcmp(method->method_name, method_name) == 0) { return method; } hash = (hash + 1) % RAVA_MAX_NATIVE_METHODS; } while (hash != start); return NULL; } RavaNativeValue_t rava_native_invoke(RavaNativeMethod_t *method, RavaNativeValue_t *args, size_t arg_count) { if (!method || !method->function) { return rava_native_void(); } return method->function(args, arg_count, method->user_data); } RavaNativeValue_t rava_native_int(int32_t val) { RavaNativeValue_t native; native.type = RAVA_NATIVE_INT; native.data.int_val = val; return native; } RavaNativeValue_t rava_native_long(int64_t val) { RavaNativeValue_t native; native.type = RAVA_NATIVE_LONG; native.data.long_val = val; return native; } RavaNativeValue_t rava_native_double(double val) { RavaNativeValue_t native; native.type = RAVA_NATIVE_DOUBLE; native.data.double_val = val; return native; } RavaNativeValue_t rava_native_boolean(bool val) { RavaNativeValue_t native; native.type = RAVA_NATIVE_BOOLEAN; native.data.bool_val = val; return native; } RavaNativeValue_t rava_native_string(const char *val) { RavaNativeValue_t native; native.type = RAVA_NATIVE_STRING; native.data.string_val = val ? strdup(val) : NULL; return native; } RavaNativeValue_t rava_native_void(void) { RavaNativeValue_t native; native.type = RAVA_NATIVE_VOID; return native; } RavaNativeValue_t rava_native_null(void) { RavaNativeValue_t native; native.type = RAVA_NATIVE_OBJECT; native.data.object_val = NULL; return native; }