mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
...
This commit is contained in:
parent
53d272ce2f
commit
a06a8918ce
@ -20,7 +20,7 @@ endif()
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR- /EHsc /utf-8 /O2")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fexceptions -O2")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fexceptions -O2 -ldl")
|
||||
endif()
|
||||
|
||||
option(PK_EXPORT_C_API "Export C API" ON)
|
||||
|
@ -6,11 +6,11 @@ with open("include/pocketpy/opcodes.h", "rt", encoding='utf-8') as f:
|
||||
OPCODES_TEXT = '\n' + f.read() + '\n'
|
||||
|
||||
pipeline = [
|
||||
["config.h", "common.h", "memory.h", "vector.h", "str.h", "tuplelist.h", "namedict.h", "error.h", "lexer.h"],
|
||||
["config.h", "export.h", "common.h", "memory.h", "vector.h", "str.h", "tuplelist.h", "namedict.h", "error.h", "lexer.h"],
|
||||
["obj.h", "dict.h", "codeobject.h", "frame.h"],
|
||||
["gc.h", "vm.h", "ceval.h", "expr.h", "compiler.h", "repl.h"],
|
||||
["_generated.h", "cffi.h", "bindings.h", "iter.h", "base64.h", "random.h", "re.h", "linalg.h", "easing.h", "io.h"],
|
||||
["export.h", "pocketpy.h"]
|
||||
["pocketpy.h"]
|
||||
]
|
||||
|
||||
copied = set()
|
||||
|
2
build.sh
2
build.sh
@ -1,3 +1,3 @@
|
||||
python3 prebuild.py
|
||||
SRC=$(find src/ -name "*.cpp")
|
||||
clang++ -std=c++17 -fno-rtti -O2 -stdlib=libc++ -Wfatal-errors -o pocketpy src2/main.cpp $SRC -Iinclude
|
||||
clang++ -std=c++17 -fno-rtti -O2 -stdlib=libc++ -Wfatal-errors -o pocketpy src2/main.cpp $SRC -Iinclude -ldl
|
@ -122,4 +122,10 @@ struct OpaquePointer{
|
||||
return VAR(self->get_##NAME()); \
|
||||
}));
|
||||
|
||||
#define PK_REGISTER_CONSTRUCTOR(T, T0) \
|
||||
vm->bind_constructor<2>(type, [](VM* vm, ArgsView args){ \
|
||||
void* p = CAST(void*, args[0]); \
|
||||
return VAR_T(T, (T0*)p); \
|
||||
});
|
||||
|
||||
} // namespace pkpy
|
@ -23,6 +23,7 @@
|
||||
#define PK_VERSION "1.0.9"
|
||||
|
||||
#include "config.h"
|
||||
#include "export.h"
|
||||
|
||||
/*******************************************************************************/
|
||||
#if PK_ENABLE_STD_FUNCTION
|
||||
@ -34,7 +35,7 @@
|
||||
#define THREAD_LOCAL thread_local
|
||||
#include <mutex>
|
||||
|
||||
struct GIL {
|
||||
struct PK_EXPORT GIL {
|
||||
inline static std::mutex _mutex;
|
||||
explicit GIL() { _mutex.lock(); }
|
||||
~GIL() { _mutex.unlock(); }
|
||||
@ -58,7 +59,7 @@ template <size_t T>
|
||||
struct NumberTraits;
|
||||
|
||||
template <>
|
||||
struct NumberTraits<4> {
|
||||
struct PK_EXPORT NumberTraits<4> {
|
||||
using int_t = int32_t;
|
||||
using float_t = float;
|
||||
|
||||
@ -73,7 +74,7 @@ struct NumberTraits<4> {
|
||||
};
|
||||
|
||||
template <>
|
||||
struct NumberTraits<8> {
|
||||
struct PK_EXPORT NumberTraits<8> {
|
||||
using int_t = int64_t;
|
||||
using float_t = double;
|
||||
|
||||
@ -95,13 +96,13 @@ static_assert(sizeof(i64) == sizeof(void*));
|
||||
static_assert(sizeof(f64) == sizeof(void*));
|
||||
static_assert(std::numeric_limits<f64>::is_iec559);
|
||||
|
||||
struct Dummy { };
|
||||
struct DummyInstance { };
|
||||
struct DummyModule { };
|
||||
struct NoReturn { };
|
||||
struct Discarded { };
|
||||
struct PK_EXPORT Dummy { };
|
||||
struct PK_EXPORT DummyInstance { };
|
||||
struct PK_EXPORT DummyModule { };
|
||||
struct PK_EXPORT NoReturn { };
|
||||
struct PK_EXPORT Discarded { };
|
||||
|
||||
struct Type {
|
||||
struct PK_EXPORT Type {
|
||||
int index;
|
||||
Type(): index(-1) {}
|
||||
Type(int index): index(index) {}
|
||||
@ -124,30 +125,32 @@ struct Type {
|
||||
|
||||
struct PyObject;
|
||||
#define PK_BITS(p) (reinterpret_cast<i64>(p))
|
||||
inline bool is_tagged(PyObject* p) noexcept { return (PK_BITS(p) & 0b11) != 0b00; }
|
||||
inline bool is_int(PyObject* p) noexcept { return (PK_BITS(p) & 0b11) == 0b01; }
|
||||
inline bool is_float(PyObject* p) noexcept { return (PK_BITS(p) & 0b11) == 0b10; }
|
||||
inline bool is_special(PyObject* p) noexcept { return (PK_BITS(p) & 0b11) == 0b11; }
|
||||
PK_EXPORT inline bool is_tagged(PyObject* p) noexcept { return (PK_BITS(p) & 0b11) != 0b00; }
|
||||
PK_EXPORT inline bool is_int(PyObject* p) noexcept { return (PK_BITS(p) & 0b11) == 0b01; }
|
||||
PK_EXPORT inline bool is_float(PyObject* p) noexcept { return (PK_BITS(p) & 0b11) == 0b10; }
|
||||
PK_EXPORT inline bool is_special(PyObject* p) noexcept { return (PK_BITS(p) & 0b11) == 0b11; }
|
||||
|
||||
inline bool is_both_int_or_float(PyObject* a, PyObject* b) noexcept {
|
||||
PK_EXPORT inline bool is_both_int_or_float(PyObject* a, PyObject* b) noexcept {
|
||||
return is_tagged(a) && is_tagged(b);
|
||||
}
|
||||
|
||||
inline bool is_both_int(PyObject* a, PyObject* b) noexcept {
|
||||
PK_EXPORT inline bool is_both_int(PyObject* a, PyObject* b) noexcept {
|
||||
return is_int(a) && is_int(b);
|
||||
}
|
||||
|
||||
inline bool is_both_float(PyObject* a, PyObject* b) noexcept {
|
||||
PK_EXPORT inline bool is_both_float(PyObject* a, PyObject* b) noexcept {
|
||||
return is_float(a) && is_float(b);
|
||||
}
|
||||
|
||||
// special singals, is_tagged() for them is true
|
||||
inline PyObject* const PY_NULL = (PyObject*)0b000011; // tagged null
|
||||
inline PyObject* const PY_OP_CALL = (PyObject*)0b100011;
|
||||
inline PyObject* const PY_OP_YIELD = (PyObject*)0b110011;
|
||||
PK_EXPORT inline PyObject* const PY_NULL = (PyObject*)0b000011; // tagged null
|
||||
PK_EXPORT inline PyObject* const PY_OP_CALL = (PyObject*)0b100011;
|
||||
PK_EXPORT inline PyObject* const PY_OP_YIELD = (PyObject*)0b110011;
|
||||
|
||||
#define ADD_MODULE_PLACEHOLDER(name) namespace pkpy { inline void add_module_##name(void* vm) { (void)vm; } }
|
||||
|
||||
} // namespace pkpy
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
@ -159,6 +162,12 @@ inline PyObject* const PY_OP_YIELD = (PyObject*)0b110011;
|
||||
#endif
|
||||
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
#elif __unix__
|
||||
|
||||
} // namespace pkpy
|
||||
#include <dlfcn.h>
|
||||
|
||||
#elif __EMSCRIPTEN__
|
||||
|
||||
#include <emscripten.h>
|
||||
|
||||
#endif
|
@ -6,9 +6,9 @@
|
||||
#include <emscripten.h>
|
||||
#define PK_EXPORT EMSCRIPTEN_KEEPALIVE
|
||||
#else
|
||||
#define PK_EXPORT __attribute__((visibility("default"))) __attribute__((used))
|
||||
#define PK_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#define PK_LEGACY_EXPORT PK_EXPORT inline
|
||||
#define PK_INLINE_EXPORT PK_EXPORT inline
|
||||
|
||||
#endif
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "easing.h"
|
||||
#include "io.h"
|
||||
#include "_generated.h"
|
||||
#include "export.h"
|
||||
#include "vm.h"
|
||||
#include "re.h"
|
||||
#include "random.h"
|
||||
@ -99,17 +98,17 @@ void add_module_gc(VM* vm);
|
||||
|
||||
/*************************GLOBAL NAMESPACE*************************/
|
||||
extern "C" {
|
||||
PK_LEGACY_EXPORT
|
||||
PK_INLINE_EXPORT
|
||||
void pkpy_free(void* p){
|
||||
free(p);
|
||||
}
|
||||
|
||||
PK_LEGACY_EXPORT
|
||||
PK_INLINE_EXPORT
|
||||
void pkpy_vm_exec(pkpy::VM* vm, const char* source){
|
||||
vm->exec(source, "main.py", pkpy::EXEC_MODE);
|
||||
}
|
||||
|
||||
PK_LEGACY_EXPORT
|
||||
PK_INLINE_EXPORT
|
||||
void pkpy_vm_exec_2(pkpy::VM* vm, const char* source, const char* filename, int mode, const char* module){
|
||||
pkpy::PyObject* mod;
|
||||
if(module == nullptr) mod = vm->_main;
|
||||
@ -120,7 +119,7 @@ extern "C" {
|
||||
vm->exec(source, filename, (pkpy::CompileMode)mode, mod);
|
||||
}
|
||||
|
||||
PK_LEGACY_EXPORT
|
||||
PK_INLINE_EXPORT
|
||||
void pkpy_vm_compile(pkpy::VM* vm, const char* source, const char* filename, int mode, bool* ok, char** res){
|
||||
try{
|
||||
pkpy::CodeObject_ code = vm->compile(source, filename, (pkpy::CompileMode)mode);
|
||||
@ -138,39 +137,39 @@ extern "C" {
|
||||
}
|
||||
}
|
||||
|
||||
PK_LEGACY_EXPORT
|
||||
PK_INLINE_EXPORT
|
||||
pkpy::REPL* pkpy_new_repl(pkpy::VM* vm){
|
||||
pkpy::REPL* p = new pkpy::REPL(vm);
|
||||
return p;
|
||||
}
|
||||
|
||||
PK_LEGACY_EXPORT
|
||||
PK_INLINE_EXPORT
|
||||
bool pkpy_repl_input(pkpy::REPL* r, const char* line){
|
||||
return r->input(line);
|
||||
}
|
||||
|
||||
PK_LEGACY_EXPORT
|
||||
PK_INLINE_EXPORT
|
||||
void pkpy_vm_add_module(pkpy::VM* vm, const char* name, const char* source){
|
||||
vm->_lazy_modules[name] = source;
|
||||
}
|
||||
|
||||
PK_LEGACY_EXPORT
|
||||
PK_INLINE_EXPORT
|
||||
pkpy::VM* pkpy_new_vm(bool enable_os=true){
|
||||
pkpy::VM* p = new pkpy::VM(enable_os);
|
||||
return p;
|
||||
}
|
||||
|
||||
PK_LEGACY_EXPORT
|
||||
PK_INLINE_EXPORT
|
||||
void pkpy_delete_vm(pkpy::VM* vm){
|
||||
delete vm;
|
||||
}
|
||||
|
||||
PK_LEGACY_EXPORT
|
||||
PK_INLINE_EXPORT
|
||||
void pkpy_delete_repl(pkpy::REPL* repl){
|
||||
delete repl;
|
||||
}
|
||||
|
||||
PK_LEGACY_EXPORT
|
||||
PK_INLINE_EXPORT
|
||||
void pkpy_vm_gc_on_delete(pkpy::VM* vm, void (*f)(pkpy::VM *, pkpy::PyObject *)){
|
||||
vm->heap._gc_on_delete = f;
|
||||
}
|
||||
|
@ -2,6 +2,38 @@
|
||||
|
||||
namespace pkpy{
|
||||
|
||||
using dylib_entry_t = PyObject*(*)(VM*, const char*);
|
||||
|
||||
#if PK_ENABLE_OS
|
||||
|
||||
#if _WIN32
|
||||
static dylib_entry_t load_dylib(const char* path){
|
||||
std::error_code ec;
|
||||
auto p = std::filesystem::absolute(path, ec);
|
||||
if(ec) return nullptr;
|
||||
HMODULE handle = LoadLibraryA(p.c_str());
|
||||
if(!handle) return nullptr;
|
||||
return (dylib_entry_t)GetProcAddress(handle, "platform_module__init__");
|
||||
}
|
||||
#else
|
||||
static dylib_entry_t load_dylib(const char* path){
|
||||
std::error_code ec;
|
||||
auto p = std::filesystem::absolute(path, ec);
|
||||
if(ec) return nullptr;
|
||||
void* handle = dlopen(p.c_str(), RTLD_LAZY);
|
||||
if(!handle) return nullptr;
|
||||
return (dylib_entry_t)dlsym(handle, "platform_module__init__");
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
static dylib_entry_t load_dylib(const char* path){
|
||||
PK_UNUSED(path);
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void init_builtins(VM* _vm) {
|
||||
#define BIND_NUM_ARITH_OPT(name, op) \
|
||||
_vm->bind##name(_vm->tp_int, [](VM* vm, PyObject* lhs, PyObject* rhs) { \
|
||||
@ -106,7 +138,19 @@ void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_vm->bind_builtin_func<1>("__import__", [](VM* vm, ArgsView args) {
|
||||
return vm->py_import(CAST(Str&, args[0]));
|
||||
const Str& name = CAST(Str&, args[0]);
|
||||
auto dot = name.sv().find_first_of(".");
|
||||
if(dot != std::string_view::npos){
|
||||
auto ext = name.sv().substr(dot);
|
||||
if(ext == ".so" || ext == ".dll" || ext == ".dylib" || ext == ".pyd"){
|
||||
dylib_entry_t entry = load_dylib(name.c_str());
|
||||
if(!entry){
|
||||
vm->_error("ImportError", "cannot load dynamic library: " + name.escape());
|
||||
}
|
||||
return entry(vm, PK_VERSION);
|
||||
}
|
||||
}
|
||||
return vm->py_import(name);
|
||||
});
|
||||
|
||||
_vm->bind_builtin_func<2>("divmod", [](VM* vm, ArgsView args) {
|
||||
|
0
tests/dylib/build.bat
Normal file
0
tests/dylib/build.bat
Normal file
2
tests/dylib/build.sh
Normal file
2
tests/dylib/build.sh
Normal file
@ -0,0 +1,2 @@
|
||||
SRC=$(find ../../src/ -name "*.cpp")
|
||||
clang++ -std=c++17 -fno-rtti -O2 -stdlib=libc++ -Wfatal-errors -o libtest.so test.cpp -I../../include -fPIC -shared
|
6
tests/dylib/main.py
Normal file
6
tests/dylib/main.py
Normal file
@ -0,0 +1,6 @@
|
||||
import os
|
||||
|
||||
print(os.getcwd())
|
||||
test = __import__('libtest.so')
|
||||
|
||||
test.hello()
|
18
tests/dylib/test.cpp
Normal file
18
tests/dylib/test.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "pocketpy.h"
|
||||
|
||||
using namespace pkpy;
|
||||
|
||||
extern "C" {
|
||||
PK_EXPORT
|
||||
PyObject* platform_module__init__(VM* vm, const char* version){
|
||||
PyObject* mod = vm->new_module("test");
|
||||
vm->_stdout(vm, "Hello from dylib!\n");
|
||||
|
||||
vm->bind(mod, "hello()", [](VM* vm, ArgsView args){
|
||||
vm->_stdout(vm, "Hello from dylib!\n");
|
||||
return vm->None;
|
||||
});
|
||||
return mod;
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user