From 13132de953707302c9fa9eb4c50f717c531674e1 Mon Sep 17 00:00:00 2001 From: malyjacob Date: Fri, 6 Sep 2024 00:03:58 +0800 Subject: [PATCH 1/5] enable windows binary module import without changing the content of script in js --- quickjs-libc.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/quickjs-libc.c b/quickjs-libc.c index e9e276db7..ebc0e78f2 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -479,7 +479,58 @@ typedef JSModuleDef *(JSInitModuleFunc)(JSContext *ctx, const char *module_name); -#if defined(_WIN32) || defined(__wasi__) +#if defined(_WIN32) +static JSModuleDef *js_module_loader_so(JSContext *ctx, + const char *module_name) +{ + JSModuleDef *m; + HINSTANCE hd; + JSInitModuleFunc *init; + // allocate enough space + char *filename = js_malloc(ctx, strlen(module_name) + 2 + 1 + 1); + if (!strchr(module_name, '/')) { + if (!filename) return NULL; + strcpy(filename, "./"); + strcpy(filename + 2, module_name); + } else { + strcpy(filename, module_name); + } + // change the suffix of filename from `.so` to `.dll` + char *start = filename + strlen(filename) - 2; + const char suffix[4] = "dll"; + strcpy(start, suffix); + + hd = LoadLibrary(filename); + if (!hd) { + JS_ThrowReferenceError( + ctx, "could not load module filename '%s' as shared library", + filename); + goto fail; + } + + init = (JSInitModuleFunc *)GetProcAddress(hd, "js_init_module"); + if (!init) { + JS_ThrowReferenceError( + ctx, "could not load module filename '%s': js_init_module not found", + filename); + goto fail; + } + + // module_name or filename? + m = init(ctx, module_name); + if (!m) { + JS_ThrowReferenceError( + ctx, "could not load module filename '%s': initialization error", + filename); + fail: + // free the filename + js_free(ctx, filename); + if (hd) FreeLibrary(hd); + return NULL; + } + return m; +} +#elif defined(__wasi__) static JSModuleDef *js_module_loader_so(JSContext *ctx, const char *module_name) { From fde104604d438d93a8930bff54a9f22f5f3650f6 Mon Sep 17 00:00:00 2001 From: malyjacob Date: Fri, 6 Sep 2024 02:51:30 +0800 Subject: [PATCH 2/5] enbale windows for dir examples --- CMakeLists.txt | 12 +++++++---- examples/fib.c | 10 ++++++++-- examples/point.c | 52 ++++++++++++++++++++++++++++++------------------ 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d4de876f8..e38941523 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,7 +93,7 @@ if(BUILD_SHARED_LIBS) message(STATUS "Building a shared library") endif() -xoption(BUILD_EXAMPLES "Build examples" OFF) +xoption(BUILD_EXAMPLES "Build examples" ON) xoption(BUILD_STATIC_QJS_EXE "Build a static qjs executable" OFF) xoption(CONFIG_ASAN "Enable AddressSanitizer (ASan)" OFF) xoption(CONFIG_MSAN "Enable MemorySanitizer (MSan)" OFF) @@ -275,7 +275,7 @@ target_link_libraries(function_source ${qjs_libs}) # Examples # -if(BUILD_EXAMPLES AND NOT WIN32) +if(BUILD_EXAMPLES) # AND NOT WIN32 add_executable(hello gen/hello.c ) @@ -292,12 +292,14 @@ if(BUILD_EXAMPLES AND NOT WIN32) target_compile_definitions(hello_module PRIVATE ${qjs_defines}) target_link_libraries(hello_module ${qjs_libs}) - if(NOT WIN32) + # if(NOT WIN32) add_library(fib MODULE examples/fib.c) set_target_properties(fib PROPERTIES PREFIX "" C_VISIBILITY_PRESET default ) + target_include_directories(fib PRIVATE .) + target_link_libraries(fib PRIVATE qjs) target_compile_definitions(fib PRIVATE JS_SHARED_LIBRARY) if(APPLE) target_link_options(fib PRIVATE -undefined dynamic_lookup) @@ -308,11 +310,13 @@ if(BUILD_EXAMPLES AND NOT WIN32) PREFIX "" C_VISIBILITY_PRESET default ) + target_include_directories(point PRIVATE .) + target_link_libraries(point PRIVATE qjs) target_compile_definitions(point PRIVATE JS_SHARED_LIBRARY) if(APPLE) target_link_options(point PRIVATE -undefined dynamic_lookup) endif() - endif() + # endif() add_executable(test_fib examples/fib.c diff --git a/examples/fib.c b/examples/fib.c index 0786378fa..6d9e4ceef 100644 --- a/examples/fib.c +++ b/examples/fib.c @@ -21,7 +21,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "../quickjs.h" +#include "quickjs.h" + +#if defined(_WIN32) +#define FIB_API __declspec(dllexport) +#else +#define FIB_API +#endif #define countof(x) (sizeof(x) / sizeof((x)[0])) @@ -61,7 +67,7 @@ static int js_fib_init(JSContext *ctx, JSModuleDef *m) #define JS_INIT_MODULE js_init_module_fib #endif -JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) +FIB_API JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) { JSModuleDef *m; m = JS_NewCModule(ctx, module_name, js_fib_init); diff --git a/examples/point.c b/examples/point.c index da22d6f5c..e7a1a5358 100644 --- a/examples/point.c +++ b/examples/point.c @@ -21,9 +21,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "../quickjs.h" + + /* point.c */ +#include "quickjs.h" #include +#if defined(_WIN32) +#define POINT_API __declspec(dllexport) +#else +#define POINT_API +#endif + #define countof(x) (sizeof(x) / sizeof((x)[0])) /* Point Class */ @@ -35,18 +43,18 @@ typedef struct { static JSClassID js_point_class_id; -static void js_point_finalizer(JSRuntime *rt, JSValue val) +static void js_point_finalizer(JSRuntime* rt, JSValue val) { - JSPointData *s = JS_GetOpaque(val, js_point_class_id); + JSPointData* s = JS_GetOpaque(val, js_point_class_id); /* Note: 's' can be NULL in case JS_SetOpaque() was not called */ js_free_rt(rt, s); } -static JSValue js_point_ctor(JSContext *ctx, - JSValue new_target, - int argc, JSValue *argv) +static JSValue js_point_ctor(JSContext* ctx, + JSValue new_target, + int argc, JSValue* argv) { - JSPointData *s; + JSPointData* s; JSValue obj = JS_UNDEFINED; JSValue proto; @@ -68,15 +76,15 @@ static JSValue js_point_ctor(JSContext *ctx, goto fail; JS_SetOpaque(obj, s); return obj; - fail: +fail: js_free(ctx, s); JS_FreeValue(ctx, obj); return JS_EXCEPTION; } -static JSValue js_point_get_xy(JSContext *ctx, JSValue this_val, int magic) +static JSValue js_point_get_xy(JSContext* ctx, JSValue this_val, int magic) { - JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); + JSPointData* s = JS_GetOpaque2(ctx, this_val, js_point_class_id); if (!s) return JS_EXCEPTION; if (magic == 0) @@ -85,9 +93,9 @@ static JSValue js_point_get_xy(JSContext *ctx, JSValue this_val, int magic) return JS_NewInt32(ctx, s->y); } -static JSValue js_point_set_xy(JSContext *ctx, JSValue this_val, JSValue val, int magic) +static JSValue js_point_set_xy(JSContext* ctx, JSValue this_val, JSValue val, int magic) { - JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); + JSPointData* s = JS_GetOpaque2(ctx, this_val, js_point_class_id); int v; if (!s) return JS_EXCEPTION; @@ -100,10 +108,10 @@ static JSValue js_point_set_xy(JSContext *ctx, JSValue this_val, JSValue val, in return JS_UNDEFINED; } -static JSValue js_point_norm(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) +static JSValue js_point_norm(JSContext* ctx, JSValue this_val, + int argc, JSValue* argv) { - JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); + JSPointData* s = JS_GetOpaque2(ctx, this_val, js_point_class_id); if (!s) return JS_EXCEPTION; return JS_NewFloat64(ctx, sqrt((double)s->x * s->x + (double)s->y * s->y)); @@ -120,10 +128,10 @@ static const JSCFunctionListEntry js_point_proto_funcs[] = { JS_CFUNC_DEF("norm", 0, js_point_norm), }; -static int js_point_init(JSContext *ctx, JSModuleDef *m) +static int js_point_init(JSContext* ctx, JSModuleDef* m) { JSValue point_proto, point_class; - JSRuntime *rt = JS_GetRuntime(ctx); + JSRuntime* rt = JS_GetRuntime(ctx); /* create the Point class */ JS_NewClassID(rt, &js_point_class_id); @@ -141,9 +149,15 @@ static int js_point_init(JSContext *ctx, JSModuleDef *m) return 0; } -JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) +#ifdef JS_SHARED_LIBRARY +#define JS_INIT_MODULE js_init_module +#else +#define JS_INIT_MODULE js_init_module_fib +#endif + +POINT_API JSModuleDef* JS_INIT_MODULE(JSContext* ctx, const char* module_name) { - JSModuleDef *m; + JSModuleDef* m; m = JS_NewCModule(ctx, module_name, js_point_init); if (!m) return NULL; From e38e3009bd030b53cffc3c513f4d393eba7ff1e4 Mon Sep 17 00:00:00 2001 From: malyjacob Date: Fri, 6 Sep 2024 09:54:44 +0800 Subject: [PATCH 3/5] fix the link bug on linux using the complier option: -fPIC --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e38941523..5644854e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,6 +177,9 @@ endif() add_library(qjs ${qjs_sources}) target_compile_definitions(qjs PRIVATE ${qjs_defines}) +if(NOT MSVC) + target_compile_options(qjs PRIVATE -fPIC) +endif() if(CMAKE_BUILD_TYPE MATCHES Debug OR DUMP_LEAKS) target_compile_definitions(qjs PRIVATE DUMP_LEAKS From 11c51f1557a6a2c962f67d771ec4f7a60bce4423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=91=E6=84=9A?= <83157862+malyjacob@users.noreply.github.com> Date: Fri, 6 Sep 2024 10:06:17 +0800 Subject: [PATCH 4/5] fix linking bug in linux when building example fib.so and point.so by appending the complier option `-fPIC` --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index c13d88bc8..68723e535 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,6 +177,9 @@ endif() add_library(qjs ${qjs_sources}) target_compile_definitions(qjs PRIVATE ${qjs_defines}) +if(NOT MSVC) + target_compile_options(qjs PRIVATE -fPIC) +endif() target_include_directories(qjs PUBLIC $ $ From bffce3c3a12c9b25e299953f17f8840f012074f5 Mon Sep 17 00:00:00 2001 From: malyjacob Date: Fri, 6 Sep 2024 16:48:05 +0800 Subject: [PATCH 5/5] fix the compiling bug in mingw --- quickjs-libc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickjs-libc.c b/quickjs-libc.c index ebc0e78f2..48e32c91a 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -508,7 +508,7 @@ static JSModuleDef *js_module_loader_so(JSContext *ctx, goto fail; } - init = (JSInitModuleFunc *)GetProcAddress(hd, "js_init_module"); + init = (JSInitModuleFunc *)(uintptr_t)GetProcAddress(hd, "js_init_module"); if (!init) { JS_ThrowReferenceError( ctx, "could not load module filename '%s': js_init_module not found",