diff --git a/.gitignore b/.gitignore index 5e644ff6..efd5fa98 100644 --- a/.gitignore +++ b/.gitignore @@ -26,9 +26,7 @@ APPS build main -pocketpy.dSYM -libpocketpy.dylib.dSYM/ -main.dSYM/ +*.dSYM docs/references.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c17d50f..eb63418c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,7 +69,7 @@ else() target_link_libraries(main ${PROJECT_NAME}) endif() -# link math library if(UNIX) target_link_libraries(${PROJECT_NAME} m) + target_link_libraries(${PROJECT_NAME} dl) endif() diff --git a/build.sh b/build.sh index 9123bf92..b9c50eb4 100644 --- a/build.sh +++ b/build.sh @@ -19,7 +19,7 @@ SRC=$(find src/ -name "*.c") echo "> Compiling and linking source files... " -clang -std=c11 -O2 -Wfatal-errors -Iinclude -DNDEBUG -o main src2/main.c $SRC -lm +clang -std=c11 -O2 -Wfatal-errors -Iinclude -DNDEBUG -o main src2/main.c $SRC -lm -ldl if [ $? -eq 0 ]; then echo "Build completed. Type \"./main\" to enter REPL." diff --git a/build_dll.sh b/build_dll.sh new file mode 100644 index 00000000..772a07fe --- /dev/null +++ b/build_dll.sh @@ -0,0 +1,6 @@ +set -e + +FLAGS="-std=c11 -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1" + +# link libpocketpy.dylib +clang $FLAGS -shared -fPIC src2/hello.c -o libhello.dylib -L. -lpocketpy diff --git a/build_g.sh b/build_g.sh index 9909b282..b9570dd3 100644 --- a/build_g.sh +++ b/build_g.sh @@ -4,7 +4,7 @@ python prebuild.py SRC=$(find src/ -name "*.c") -FLAGS="-std=c11 -lm -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1" +FLAGS="-std=c11 -lm -ldl -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1" SANITIZE_FLAGS="-fsanitize=address,leak,undefined" diff --git a/run_profile.sh b/run_profile.sh index cc1528ea..28cc8c37 100644 --- a/run_profile.sh +++ b/run_profile.sh @@ -4,7 +4,7 @@ python prebuild.py SRC=$(find src/ -name "*.c") -gcc -pg -Og -std=c11 -Wfatal-errors -o main $SRC src2/main.c -Iinclude -lm -DNDEBUG -flto +gcc -pg -Og -std=c11 -Wfatal-errors -o main $SRC src2/main.c -Iinclude -lm -ldl -DNDEBUG -flto ./main benchmarks/fib.py gprof main gmon.out > gprof.txt rm gmon.out diff --git a/run_tests.sh b/run_tests.sh index 14915a2f..d827701b 100644 --- a/run_tests.sh +++ b/run_tests.sh @@ -4,7 +4,7 @@ python prebuild.py SRC=$(find src/ -name "*.c") -clang -std=c11 --coverage -O1 -Wfatal-errors -o main src2/main.c $SRC -Iinclude -DPK_ENABLE_OS=1 -DPK_ENABLE_PROFILER=1 -lm -DNDEBUG +clang -std=c11 --coverage -O1 -Wfatal-errors -o main src2/main.c $SRC -Iinclude -DPK_ENABLE_OS=1 -DPK_ENABLE_PROFILER=1 -lm -ldl -DNDEBUG python scripts/run_tests.py diff --git a/src/interpreter/dll.c b/src/interpreter/dll.c new file mode 100644 index 00000000..c60b8ec2 --- /dev/null +++ b/src/interpreter/dll.c @@ -0,0 +1,37 @@ +#include "pocketpy/pocketpy.h" + +#if PK_IS_DESKTOP_PLATFORM + +#ifdef _WIN32 +void* LoadLibraryA(const char*); +void* GetProcAddress(void*, const char*); +#else +#include +#endif + +typedef bool (*py_module_initialize_t)() PY_RAISE PY_RETURN; + +int load_module_from_dll_desktop_only(const char* path) PY_RAISE PY_RETURN { + const char* f_init_name = "py_module_initialize"; +#ifdef _WIN32 + void* dll = LoadLibraryA(path); + if(dll == NULL) return 0; + py_module_initialize_t f_init = (py_module_initialize_t)GetProcAddress(dll, f_init_name); +#else + void* dll = dlopen(path, RTLD_LAZY); + if(dll == NULL) return 0; + py_module_initialize_t f_init = (py_module_initialize_t)dlsym(dll, f_init_name); +#endif + if(f_init == NULL) return 0; + bool success = f_init(); + if(!success) return -1; + return 1; +} + +#else + +int load_module_from_dll_desktop_only(const char* path) PY_RAISE PY_RETURN { + return 0; +} + +#endif \ No newline at end of file diff --git a/src/public/internal.c b/src/public/internal.c index c1f8dcd4..fe7ab656 100644 --- a/src/public/internal.c +++ b/src/public/internal.c @@ -20,6 +20,10 @@ static VM pk_default_vm; static VM* pk_all_vm[16]; void py_initialize() { + if(pk_current_vm){ + c11__abort("py_initialize() can only be called once!"); + } + MemoryPools__initialize(); py_Name__initialize(); diff --git a/src/public/modules.c b/src/public/modules.c index df1a928a..6be8c503 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -63,9 +63,9 @@ py_Ref py_newmodule(const char* path) { return py_getmodule(path); } -int py_import(const char* path_cstr) { - // printf("importing %s\n", path_cstr); +int load_module_from_dll_desktop_only(const char* path) PY_RAISE PY_RETURN; +int py_import(const char* path_cstr) { VM* vm = pk_current_vm; c11_sv path = {path_cstr, strlen(path_cstr)}; if(path.size == 0) return ValueError("empty module name"); @@ -142,7 +142,8 @@ int py_import(const char* path_cstr) { c11_string__delete(filename); c11_string__delete(slashed_path); - return 0; + // not found + return load_module_from_dll_desktop_only(path_cstr); __SUCCESS: do { diff --git a/src2/hello.c b/src2/hello.c new file mode 100644 index 00000000..92520fdb --- /dev/null +++ b/src2/hello.c @@ -0,0 +1,15 @@ +#include "pocketpy.h" + +static bool hello_add(int argc, py_Ref argv){ + PY_CHECK_ARGC(2); + return py_binaryadd(py_arg(0), py_arg(1)); +} + +bool py_module_initialize(){ + py_GlobalRef mod = py_newmodule("hello"); + + py_bindfunc(mod, "add", hello_add); + + py_assign(py_retval(), mod); + return true; +} \ No newline at end of file