diff --git a/CMakeLists.txt b/CMakeLists.txt index c4219aba2..fa9a4844a 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) @@ -177,6 +177,12 @@ endif() add_library(qjs ${qjs_sources}) target_compile_definitions(qjs PRIVATE ${qjs_defines}) +if(NOT MSVC) + target_compile_options(qjs PRIVATE -fPIC) +endif() +if(NOT MSVC) + target_compile_options(qjs PRIVATE -fPIC) +endif() target_include_directories(qjs PUBLIC $ $ @@ -270,7 +276,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 ) @@ -287,12 +293,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) @@ -303,11 +311,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; diff --git a/quickjs-libc.c b/quickjs-libc.c index e9e276db7..48e32c91a 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 *)(uintptr_t)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) {