mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
...
This commit is contained in:
parent
bf1c1bd678
commit
6062e34a29
@ -164,20 +164,18 @@ void _bind(VM* vm, PyObject* obj, const char* sig, Ret(T::*func)(Params...)){
|
|||||||
return VAR(self == other); \
|
return VAR(self == other); \
|
||||||
}); \
|
}); \
|
||||||
|
|
||||||
#define PY_POINTER_LIKE(wT) \
|
#define PY_POINTER_SETGETITEM(wT) \
|
||||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ \
|
using vT = std::remove_pointer_t<decltype(std::declval<wT>()._())>; \
|
||||||
|
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ \
|
||||||
wT& self = _CAST(wT&, _0); \
|
wT& self = _CAST(wT&, _0); \
|
||||||
if(!vm->isinstance(_1, wT::_type(vm))) return vm->NotImplemented; \
|
i64 i = CAST(i64, _1); \
|
||||||
wT& other = _CAST(wT&, _1); \
|
return VAR(self._()[i]); \
|
||||||
return VAR(self._() == other._()); \
|
|
||||||
}); \
|
}); \
|
||||||
vm->bind__hash__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){ \
|
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1, PyObject* _2){ \
|
||||||
wT& self = _CAST(wT&, obj); \
|
wT& self = _CAST(wT&, _0); \
|
||||||
return reinterpret_cast<i64>(self._()); \
|
i64 i = CAST(i64, _1); \
|
||||||
|
self._()[i] = CAST(vT, _2); \
|
||||||
|
return vm->None; \
|
||||||
}); \
|
}); \
|
||||||
vm->bind_property(type, "_value: int", [](VM* vm, ArgsView args){ \
|
|
||||||
wT& self = _CAST(wT&, args[0]); \
|
|
||||||
return VAR(reinterpret_cast<i64>(self._())); \
|
|
||||||
});
|
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
@ -29,9 +29,6 @@ namespace pkpy {
|
|||||||
|
|
||||||
#define VAR_T(T, ...) vm->heap.gcnew<T>(T::_type(vm), __VA_ARGS__)
|
#define VAR_T(T, ...) vm->heap.gcnew<T>(T::_type(vm), __VA_ARGS__)
|
||||||
|
|
||||||
inline PyObject* py_var(VM* vm, void* p);
|
|
||||||
inline PyObject* py_var(VM* vm, char* p);
|
|
||||||
|
|
||||||
struct VoidP{
|
struct VoidP{
|
||||||
PY_CLASS(VoidP, c, void_p)
|
PY_CLASS(VoidP, c, void_p)
|
||||||
|
|
||||||
@ -58,6 +55,10 @@ struct VoidP{
|
|||||||
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline PyObject* py_var(VM* vm, void* p){
|
||||||
|
return VAR_T(VoidP, p);
|
||||||
|
}
|
||||||
|
|
||||||
struct C99Struct{
|
struct C99Struct{
|
||||||
PY_CLASS(C99Struct, c, struct)
|
PY_CLASS(C99Struct, c, struct)
|
||||||
|
|
||||||
@ -81,33 +82,14 @@ struct C99Struct{
|
|||||||
}
|
}
|
||||||
|
|
||||||
C99Struct(const C99Struct& other): C99Struct(other.p, other.size){}
|
C99Struct(const C99Struct& other): C99Struct(other.p, other.size){}
|
||||||
|
|
||||||
~C99Struct(){ if(p!=_inlined) free(p); }
|
~C99Struct(){ if(p!=_inlined) free(p); }
|
||||||
|
|
||||||
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ReflType{
|
|
||||||
std::string_view name;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
inline static std::map<std::string_view, ReflType> _refl_types;
|
|
||||||
|
|
||||||
inline void add_refl_type(std::string_view name, size_t size){
|
|
||||||
ReflType type{name, size};
|
|
||||||
_refl_types[name] = std::move(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static_assert(sizeof(Py_<C99Struct>) <= 64);
|
static_assert(sizeof(Py_<C99Struct>) <= 64);
|
||||||
static_assert(sizeof(Py_<Tuple>) <= 64);
|
static_assert(sizeof(Py_<Tuple>) <= 64);
|
||||||
|
|
||||||
inline PyObject* py_var(VM* vm, void* p){
|
|
||||||
return VAR_T(VoidP, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline PyObject* py_var(VM* vm, char* p){
|
|
||||||
return VAR_T(VoidP, p);
|
|
||||||
}
|
|
||||||
/***********************************************/
|
/***********************************************/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T to_void_p(VM* vm, PyObject* var){
|
T to_void_p(VM* vm, PyObject* var){
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include <random>
|
#include <random>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
|
||||||
#define PK_VERSION "1.2.3"
|
#define PK_VERSION "1.2.4"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
@ -167,7 +167,8 @@ public:
|
|||||||
PyObject* py_iter(PyObject* obj);
|
PyObject* py_iter(PyObject* obj);
|
||||||
|
|
||||||
PyObject* find_name_in_mro(PyObject* cls, StrName name);
|
PyObject* find_name_in_mro(PyObject* cls, StrName name);
|
||||||
bool isinstance(PyObject* obj, Type cls_t);
|
bool isinstance(PyObject* obj, Type base);
|
||||||
|
bool issubclass(Type cls, Type base);
|
||||||
PyObject* exec(Str source, Str filename, CompileMode mode, PyObject* _module=nullptr);
|
PyObject* exec(Str source, Str filename, CompileMode mode, PyObject* _module=nullptr);
|
||||||
PyObject* exec(Str source);
|
PyObject* exec(Str source);
|
||||||
PyObject* eval(Str source);
|
PyObject* eval(Str source);
|
||||||
|
@ -1,64 +1,53 @@
|
|||||||
from typing import overload
|
from typing import overload, Generic, TypeVar
|
||||||
|
|
||||||
def malloc(size: int) -> 'void_p': ...
|
def malloc(size: int) -> 'void_p': ...
|
||||||
def free(ptr: 'void_p') -> None: ...
|
def free(ptr: 'void_p') -> None: ...
|
||||||
def sizeof(type: str) -> int: ...
|
|
||||||
def memset(ptr: 'void_p', value: int, size: int) -> None: ...
|
def memset(ptr: 'void_p', value: int, size: int) -> None: ...
|
||||||
def memcpy(dst: 'void_p', src: 'void_p', size: int) -> None: ...
|
def memcpy(dst: 'void_p', src: 'void_p', size: int) -> None: ...
|
||||||
|
|
||||||
|
T = TypeVar('T')
|
||||||
|
Tp = TypeVar('Tp', bound='void_p')
|
||||||
|
|
||||||
|
def p_cast(ptr: 'void_p', cls: type[T]) -> T:
|
||||||
|
"""Cast a pointer to a specific type."""
|
||||||
|
def p_value(ptr: 'void_p') -> int:
|
||||||
|
"""Get the value of a pointer."""
|
||||||
|
def pp_deref(ptr: Tp) -> Tp:
|
||||||
|
"""Dereference a double pointer."""
|
||||||
|
|
||||||
class void_p:
|
class void_p:
|
||||||
def __init__(self, addr: int): ...
|
def __init__(self, addr: int): ...
|
||||||
def __add__(self, i: int) -> 'void_p': ...
|
|
||||||
def __sub__(self, i: int) -> 'void_p': ...
|
|
||||||
def __eq__(self, other: 'void_p') -> bool: ...
|
def __eq__(self, other: 'void_p') -> bool: ...
|
||||||
def __ne__(self, other: 'void_p') -> bool: ...
|
def __ne__(self, other: 'void_p') -> bool: ...
|
||||||
|
def __lt__(self, other: 'void_p') -> bool: ...
|
||||||
|
def __le__(self, other: 'void_p') -> bool: ...
|
||||||
|
def __gt__(self, other: 'void_p') -> bool: ...
|
||||||
|
def __ge__(self, other: 'void_p') -> bool: ...
|
||||||
def __hash__(self) -> int: ...
|
def __hash__(self) -> int: ...
|
||||||
|
def __repr__(self) -> str: ...
|
||||||
|
|
||||||
def hex(self) -> str: ...
|
class Pointer(Generic[T], void_p):
|
||||||
|
def read(self) -> T: ...
|
||||||
|
def write(self, value: T) -> None: ...
|
||||||
|
def __getitem__(self, index: int) -> T: ...
|
||||||
|
def __setitem__(self, index: int, value: T) -> None: ...
|
||||||
|
|
||||||
@property
|
class char_p(Pointer[int]): pass
|
||||||
def _value(self) -> int: ...
|
class uchar_p(Pointer[int]): pass
|
||||||
|
class short_p(Pointer[int]): pass
|
||||||
def read_char(self) -> int: ...
|
class ushort_p(Pointer[int]): pass
|
||||||
def read_uchar(self) -> int: ...
|
class int_p(Pointer[int]): pass
|
||||||
def read_short(self) -> int: ...
|
class uint_p(Pointer[int]): pass
|
||||||
def read_ushort(self) -> int: ...
|
class long_p(Pointer[int]): pass
|
||||||
def read_int(self) -> int: ...
|
class ulong_p(Pointer[int]): pass
|
||||||
def read_uint(self) -> int: ...
|
class longlong_p(Pointer[int]): pass
|
||||||
def read_long(self) -> int: ...
|
class ulonglong_p(Pointer[int]): pass
|
||||||
def read_ulong(self) -> int: ...
|
class float_p(Pointer[float]): pass
|
||||||
def read_longlong(self) -> int: ...
|
class double_p(Pointer[float]): pass
|
||||||
def read_ulonglong(self) -> int: ...
|
class bool_p(Pointer[bool]): pass
|
||||||
def read_float(self) -> float: ...
|
|
||||||
def read_double(self) -> float: ...
|
|
||||||
def read_bool(self) -> bool: ...
|
|
||||||
def read_void_p(self) -> 'void_p': ...
|
|
||||||
def read_bytes(self, size: int) -> bytes: ...
|
|
||||||
def read_struct(self, size: int) -> 'struct': ...
|
|
||||||
|
|
||||||
def write_char(self, value: int) -> None: ...
|
|
||||||
def write_uchar(self, value: int) -> None: ...
|
|
||||||
def write_short(self, value: int) -> None: ...
|
|
||||||
def write_ushort(self, value: int) -> None: ...
|
|
||||||
def write_int(self, value: int) -> None: ...
|
|
||||||
def write_uint(self, value: int) -> None: ...
|
|
||||||
def write_long(self, value: int) -> None: ...
|
|
||||||
def write_ulong(self, value: int) -> None: ...
|
|
||||||
def write_longlong(self, value: int) -> None: ...
|
|
||||||
def write_ulonglong(self, value: int) -> None: ...
|
|
||||||
def write_float(self, value: float) -> None: ...
|
|
||||||
def write_double(self, value: float) -> None: ...
|
|
||||||
def write_bool(self, value: bool) -> None: ...
|
|
||||||
def write_void_p(self, value: 'void_p') -> None: ...
|
|
||||||
def write_bytes(self, value: bytes) -> None: ...
|
|
||||||
def write_struct(self, value: 'struct') -> None: ...
|
|
||||||
|
|
||||||
class struct:
|
class struct:
|
||||||
@overload
|
|
||||||
def __init__(self, size: int): ...
|
def __init__(self, size: int): ...
|
||||||
@overload
|
|
||||||
def __init__(self, buffer: bytes): ...
|
|
||||||
|
|
||||||
def addr(self) -> 'void_p': ...
|
def addr(self) -> 'void_p': ...
|
||||||
def copy(self) -> 'struct': ...
|
def copy(self) -> 'struct': ...
|
||||||
def sizeof(self) -> int: ...
|
def sizeof(self) -> int: ...
|
||||||
@ -79,7 +68,6 @@ class struct:
|
|||||||
def read_double(self, offset=0) -> float: ...
|
def read_double(self, offset=0) -> float: ...
|
||||||
def read_bool(self, offset=0) -> bool: ...
|
def read_bool(self, offset=0) -> bool: ...
|
||||||
def read_void_p(self, offset=0) -> 'void_p': ...
|
def read_void_p(self, offset=0) -> 'void_p': ...
|
||||||
|
|
||||||
def write_char(self, value: int, offset=0) -> None: ...
|
def write_char(self, value: int, offset=0) -> None: ...
|
||||||
def write_uchar(self, value: int, offset=0) -> None: ...
|
def write_uchar(self, value: int, offset=0) -> None: ...
|
||||||
def write_short(self, value: int, offset=0) -> None: ...
|
def write_short(self, value: int, offset=0) -> None: ...
|
||||||
@ -109,48 +97,14 @@ def float_(val: float) -> struct: ...
|
|||||||
def double_(val: float) -> struct: ...
|
def double_(val: float) -> struct: ...
|
||||||
def bool_(val: bool) -> struct: ...
|
def bool_(val: bool) -> struct: ...
|
||||||
|
|
||||||
char_p = void_p
|
|
||||||
uchar_p = void_p
|
|
||||||
short_p = void_p
|
|
||||||
ushort_p = void_p
|
|
||||||
int_p = void_p
|
|
||||||
uint_p = void_p
|
|
||||||
long_p = void_p
|
|
||||||
ulong_p = void_p
|
|
||||||
longlong_p = void_p
|
|
||||||
ulonglong_p = void_p
|
|
||||||
float_p = void_p
|
|
||||||
double_p = void_p
|
|
||||||
bool_p = void_p
|
|
||||||
|
|
||||||
class array(struct):
|
|
||||||
count: int
|
|
||||||
item_size: int
|
|
||||||
|
|
||||||
def __new__(cls, count: int, item_size: int): ...
|
|
||||||
def __getitem__(self, index: int) -> struct: ...
|
|
||||||
def __setitem__(self, index: int, value: struct) -> None: ...
|
|
||||||
def __len__(self) -> int: ...
|
|
||||||
|
|
||||||
from typing import Generic, TypeVar
|
|
||||||
|
|
||||||
T = TypeVar('T')
|
|
||||||
|
|
||||||
class _StructLike(Generic[T]):
|
class _StructLike(Generic[T]):
|
||||||
def to_struct(self) -> struct: ...
|
def to_struct(self) -> struct: ...
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_struct(cls, s: struct) -> T: ...
|
def from_struct(cls, s: struct) -> T: ...
|
||||||
|
|
||||||
def addr(self) -> '_PointerLike[T]': ...
|
def addr(self) -> 'Pointer[T]': ...
|
||||||
def sizeof(self) -> int: ...
|
|
||||||
def copy(self) -> T: ...
|
def copy(self) -> T: ...
|
||||||
|
def sizeof(self) -> int: ...
|
||||||
def __eq__(self, other: T) -> bool: ...
|
def __eq__(self, other: T) -> bool: ...
|
||||||
def __ne__(self, other: T) -> bool: ...
|
def __ne__(self, other: T) -> bool: ...
|
||||||
|
|
||||||
class _PointerLike(Generic[T]):
|
|
||||||
def __eq__(self, other) -> bool: ...
|
|
||||||
def __ne__(self, other) -> bool: ...
|
|
||||||
def __hash__(self) -> int: ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def _value(self) -> int: ...
|
|
||||||
|
27
python/c.py
27
python/c.py
@ -1,27 +0,0 @@
|
|||||||
class array(struct):
|
|
||||||
item_count: int
|
|
||||||
item_size: int
|
|
||||||
|
|
||||||
def __new__(cls, item_count: int, item_size: int = 1):
|
|
||||||
obj = struct.__new__(cls, item_count * item_size)
|
|
||||||
obj._enable_instance_dict()
|
|
||||||
obj.item_count = item_count
|
|
||||||
obj.item_size = item_size
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def __getitem__(self, index: int) -> struct:
|
|
||||||
if index < 0 or index >= self.item_count:
|
|
||||||
raise IndexError("array index out of range")
|
|
||||||
p = self.addr() + self.item_size * index
|
|
||||||
return p.read_struct(self.item_size)
|
|
||||||
|
|
||||||
def __setitem__(self, index: int, value: struct) -> None:
|
|
||||||
if index < 0 or index >= self.item_count:
|
|
||||||
raise IndexError("array index out of range")
|
|
||||||
if value.sizeof() != self.item_size:
|
|
||||||
raise ValueError(f"array item size mismatch: {value.sizeof()} != {self.item_size}")
|
|
||||||
p = self.addr() + self.item_size * index
|
|
||||||
p.write_struct(value)
|
|
||||||
|
|
||||||
def __len__(self) -> int:
|
|
||||||
return self.item_count
|
|
191
src/cffi.cpp
191
src/cffi.cpp
@ -1,5 +1,4 @@
|
|||||||
#include "pocketpy/cffi.h"
|
#include "pocketpy/cffi.h"
|
||||||
#include "pocketpy/str.h"
|
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
@ -10,26 +9,19 @@ namespace pkpy{
|
|||||||
return vm->heap.gcnew<VoidP>(cls, reinterpret_cast<void*>(addr));
|
return vm->heap.gcnew<VoidP>(cls, reinterpret_cast<void*>(addr));
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_method<0>(type, "hex", [](VM* vm, ArgsView args){
|
vm->bind__hash__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
||||||
VoidP& self = _CAST(VoidP&, args[0]);
|
VoidP& self = _CAST(VoidP&, obj);
|
||||||
return VAR(self.hex());
|
return reinterpret_cast<i64>(self.ptr);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
||||||
VoidP& self = _CAST(VoidP&, obj);
|
VoidP& self = _CAST(VoidP&, obj);
|
||||||
std::stringstream ss;
|
return VAR(fmt("<void* at ", self.hex(), ">"));
|
||||||
ss << "<void* at " << self.hex() << ">";
|
|
||||||
return VAR(ss.str());
|
|
||||||
});
|
|
||||||
|
|
||||||
vm->bind_property(type, "_value: int", [](VM* vm, ArgsView args){
|
|
||||||
VoidP& self = _CAST(VoidP&, args[0]);
|
|
||||||
return VAR(reinterpret_cast<i64>(self.ptr));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
#define BIND_CMP(name, op) \
|
#define BIND_CMP(name, op) \
|
||||||
vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){ \
|
vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){ \
|
||||||
if(!is_non_tagged_type(rhs, VoidP::_type(vm))) return vm->NotImplemented; \
|
if(!vm->isinstance(rhs, VoidP::_type(vm))) return vm->NotImplemented; \
|
||||||
return VAR(_CAST(VoidP&, lhs) op _CAST(VoidP&, rhs)); \
|
return VAR(_CAST(VoidP&, lhs) op _CAST(VoidP&, rhs)); \
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -40,81 +32,14 @@ namespace pkpy{
|
|||||||
BIND_CMP(__ge__, >=)
|
BIND_CMP(__ge__, >=)
|
||||||
|
|
||||||
#undef BIND_CMP
|
#undef BIND_CMP
|
||||||
|
|
||||||
vm->bind__hash__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
|
||||||
VoidP& self = _CAST(VoidP&, obj);
|
|
||||||
return reinterpret_cast<i64>(self.ptr);
|
|
||||||
});
|
|
||||||
|
|
||||||
vm->bind__add__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){
|
|
||||||
VoidP& self = _CAST(VoidP&, lhs);
|
|
||||||
i64 offset = CAST(i64, rhs);
|
|
||||||
return VAR_T(VoidP, (char*)self.ptr + offset);
|
|
||||||
});
|
|
||||||
|
|
||||||
vm->bind__sub__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){
|
|
||||||
VoidP& self = _CAST(VoidP&, lhs);
|
|
||||||
i64 offset = CAST(i64, rhs);
|
|
||||||
return VAR_T(VoidP, (char*)self.ptr - offset);
|
|
||||||
});
|
|
||||||
|
|
||||||
#define BIND_SETGET(T, name) \
|
|
||||||
vm->bind_method<0>(type, "read_" name, [](VM* vm, ArgsView args){ \
|
|
||||||
VoidP& self = _CAST(VoidP&, args[0]); \
|
|
||||||
return VAR(*(T*)self.ptr); \
|
|
||||||
}); \
|
|
||||||
vm->bind_method<1>(type, "write_" name, [](VM* vm, ArgsView args){ \
|
|
||||||
VoidP& self = _CAST(VoidP&, args[0]); \
|
|
||||||
*(T*)self.ptr = CAST(T, args[1]); \
|
|
||||||
return vm->None; \
|
|
||||||
});
|
|
||||||
|
|
||||||
BIND_SETGET(char, "char")
|
|
||||||
BIND_SETGET(unsigned char, "uchar")
|
|
||||||
BIND_SETGET(short, "short")
|
|
||||||
BIND_SETGET(unsigned short, "ushort")
|
|
||||||
BIND_SETGET(int, "int")
|
|
||||||
BIND_SETGET(unsigned int, "uint")
|
|
||||||
BIND_SETGET(long, "long")
|
|
||||||
BIND_SETGET(unsigned long, "ulong")
|
|
||||||
BIND_SETGET(long long, "longlong")
|
|
||||||
BIND_SETGET(unsigned long long, "ulonglong")
|
|
||||||
BIND_SETGET(float, "float")
|
|
||||||
BIND_SETGET(double, "double")
|
|
||||||
BIND_SETGET(bool, "bool")
|
|
||||||
BIND_SETGET(void*, "void_p")
|
|
||||||
|
|
||||||
vm->bind_method<1>(type, "read_bytes", [](VM* vm, ArgsView args){
|
|
||||||
VoidP& self = _CAST(VoidP&, args[0]);
|
|
||||||
i64 size = CAST(i64, args[1]);
|
|
||||||
std::vector<char> buffer(size);
|
|
||||||
memcpy(buffer.data(), self.ptr, size);
|
|
||||||
return VAR(Bytes(std::move(buffer)));
|
|
||||||
});
|
|
||||||
|
|
||||||
vm->bind_method<1>(type, "write_bytes", [](VM* vm, ArgsView args){
|
|
||||||
VoidP& self = _CAST(VoidP&, args[0]);
|
|
||||||
Bytes& bytes = CAST(Bytes&, args[1]);
|
|
||||||
memcpy(self.ptr, bytes.data(), bytes.size());
|
|
||||||
return vm->None;
|
|
||||||
});
|
|
||||||
|
|
||||||
#undef BIND_SETGET
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void C99Struct::_register(VM* vm, PyObject* mod, PyObject* type){
|
void C99Struct::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind_constructor<2>(type, [](VM* vm, ArgsView args){
|
vm->bind_constructor<2>(type, [](VM* vm, ArgsView args){
|
||||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||||
if(is_int(args[1])){
|
int size = CAST(int, args[1]);
|
||||||
int size = _CAST(int, args[1]);
|
|
||||||
return vm->heap.gcnew<C99Struct>(cls, size);
|
return vm->heap.gcnew<C99Struct>(cls, size);
|
||||||
}
|
|
||||||
if(is_non_tagged_type(args[1], vm->tp_bytes)){
|
|
||||||
const Bytes& b = _CAST(Bytes&, args[1]);
|
|
||||||
return vm->heap.gcnew<C99Struct>(cls, (void*)b.data(), b.size());
|
|
||||||
}
|
|
||||||
vm->TypeError("expected int or bytes");
|
|
||||||
return vm->None;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
||||||
@ -161,7 +86,6 @@ namespace pkpy{
|
|||||||
*(T*)ptr = CAST(T, args[1]); \
|
*(T*)ptr = CAST(T, args[1]); \
|
||||||
return vm->None; \
|
return vm->None; \
|
||||||
});
|
});
|
||||||
|
|
||||||
BIND_SETGET(char, "char")
|
BIND_SETGET(char, "char")
|
||||||
BIND_SETGET(unsigned char, "uchar")
|
BIND_SETGET(unsigned char, "uchar")
|
||||||
BIND_SETGET(short, "short")
|
BIND_SETGET(short, "short")
|
||||||
@ -177,22 +101,6 @@ namespace pkpy{
|
|||||||
BIND_SETGET(bool, "bool")
|
BIND_SETGET(bool, "bool")
|
||||||
BIND_SETGET(void*, "void_p")
|
BIND_SETGET(void*, "void_p")
|
||||||
#undef BIND_SETGET
|
#undef BIND_SETGET
|
||||||
|
|
||||||
// patch VoidP
|
|
||||||
type = vm->_t(VoidP::_type(vm));
|
|
||||||
|
|
||||||
vm->bind_method<1>(type, "read_struct", [](VM* vm, ArgsView args){
|
|
||||||
VoidP& self = _CAST(VoidP&, args[0]);
|
|
||||||
int size = CAST(int, args[1]);
|
|
||||||
return VAR_T(C99Struct, self.ptr, size);
|
|
||||||
});
|
|
||||||
|
|
||||||
vm->bind_method<1>(type, "write_struct", [](VM* vm, ArgsView args){
|
|
||||||
VoidP& self = _CAST(VoidP&, args[0]);
|
|
||||||
C99Struct& other = CAST(C99Struct&, args[1]);
|
|
||||||
memcpy(self.ptr, other.p, other.size);
|
|
||||||
return vm->None;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_module_c(VM* vm){
|
void add_module_c(VM* vm){
|
||||||
@ -225,28 +133,81 @@ void add_module_c(VM* vm){
|
|||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vm->bind_func<1>(mod, "sizeof", [](VM* vm, ArgsView args){
|
|
||||||
const Str& type = CAST(Str&, args[0]);
|
|
||||||
auto it = _refl_types.find(type.sv());
|
|
||||||
if(it != _refl_types.end()) return VAR(it->second.size);
|
|
||||||
vm->ValueError("not a valid c99 type");
|
|
||||||
return vm->None;
|
|
||||||
});
|
|
||||||
|
|
||||||
VoidP::register_class(vm, mod);
|
VoidP::register_class(vm, mod);
|
||||||
C99Struct::register_class(vm, mod);
|
C99Struct::register_class(vm, mod);
|
||||||
mod->attr().set("NULL", VAR_T(VoidP, nullptr));
|
mod->attr().set("NULL", VAR_T(VoidP, nullptr));
|
||||||
|
|
||||||
add_refl_type("void_p", sizeof(void*));
|
vm->bind(mod, "p_cast(ptr: 'void_p', cls: type[T]) -> T", [](VM* vm, ArgsView args){
|
||||||
PyObject* void_p_t = mod->attr("void_p");
|
VoidP& ptr = CAST(VoidP&, args[0]);
|
||||||
|
vm->check_non_tagged_type(args[1], vm->tp_type);
|
||||||
|
Type cls = PK_OBJ_GET(Type, args[1]);
|
||||||
|
if(!vm->issubclass(cls, VoidP::_type(vm))){
|
||||||
|
vm->ValueError("expected a subclass of void_p");
|
||||||
|
}
|
||||||
|
return vm->heap.gcnew<VoidP>(cls, ptr.ptr);
|
||||||
|
});
|
||||||
|
|
||||||
#define BIND_PRIMITIVE(T, name) \
|
vm->bind(mod, "p_value(ptr: 'void_p') -> int", [](VM* vm, ArgsView args){
|
||||||
vm->bind_func<1>(mod, name "_", [](VM* vm, ArgsView args){ \
|
VoidP& ptr = CAST(VoidP&, args[0]);
|
||||||
|
return VAR(reinterpret_cast<i64>(ptr.ptr));
|
||||||
|
});
|
||||||
|
|
||||||
|
vm->bind(mod, "pp_deref(ptr: Tp) -> Tp", [](VM* vm, ArgsView args){
|
||||||
|
VoidP& ptr = CAST(VoidP&, args[0]);
|
||||||
|
void* value = *reinterpret_cast<void**>(ptr.ptr);
|
||||||
|
return vm->heap.gcnew<VoidP>(args[0]->type, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
PyObject* type;
|
||||||
|
Type type_t;
|
||||||
|
|
||||||
|
#define BIND_PRIMITIVE(T, CNAME) \
|
||||||
|
vm->bind_func<1>(mod, CNAME "_", [](VM* vm, ArgsView args){ \
|
||||||
T val = CAST(T, args[0]); \
|
T val = CAST(T, args[0]); \
|
||||||
return VAR_T(C99Struct, &val, sizeof(T)); \
|
return VAR_T(C99Struct, &val, sizeof(T)); \
|
||||||
}); \
|
}); \
|
||||||
add_refl_type(name, sizeof(T)); \
|
type = vm->new_type_object(mod, CNAME "_p", VoidP::_type(vm)); \
|
||||||
mod->attr().set(name "_p", void_p_t); \
|
type_t = PK_OBJ_GET(Type, type); \
|
||||||
|
vm->bind_method<0>(type, "read", [](VM* vm, ArgsView args){ \
|
||||||
|
VoidP& voidp = PK_OBJ_GET(VoidP, args[0]); \
|
||||||
|
T* target = (T*)voidp.ptr; \
|
||||||
|
return VAR(*target); \
|
||||||
|
}); \
|
||||||
|
vm->bind_method<1>(type, "write", [](VM* vm, ArgsView args){ \
|
||||||
|
VoidP& voidp = PK_OBJ_GET(VoidP, args[0]); \
|
||||||
|
T val = CAST(T, args[1]); \
|
||||||
|
T* target = (T*)voidp.ptr; \
|
||||||
|
*target = val; \
|
||||||
|
return vm->None; \
|
||||||
|
}); \
|
||||||
|
vm->bind__getitem__(type_t, [](VM* vm, PyObject* obj, PyObject* index){ \
|
||||||
|
VoidP& voidp = PK_OBJ_GET(VoidP, obj); \
|
||||||
|
i64 offset = CAST(i64, index); \
|
||||||
|
T* target = (T*)voidp.ptr; \
|
||||||
|
return VAR(target[offset]); \
|
||||||
|
}); \
|
||||||
|
vm->bind__setitem__(type_t, [](VM* vm, PyObject* obj, PyObject* index, PyObject* value){ \
|
||||||
|
VoidP& voidp = PK_OBJ_GET(VoidP, obj); \
|
||||||
|
i64 offset = CAST(i64, index); \
|
||||||
|
T* target = (T*)voidp.ptr; \
|
||||||
|
target[offset] = CAST(T, value); \
|
||||||
|
}); \
|
||||||
|
vm->bind__add__(type_t, [](VM* vm, PyObject* lhs, PyObject* rhs){ \
|
||||||
|
VoidP& voidp = PK_OBJ_GET(VoidP, lhs); \
|
||||||
|
i64 offset = CAST(i64, rhs); \
|
||||||
|
T* target = (T*)voidp.ptr; \
|
||||||
|
return vm->heap.gcnew<VoidP>(lhs->type, target + offset); \
|
||||||
|
}); \
|
||||||
|
vm->bind__sub__(type_t, [](VM* vm, PyObject* lhs, PyObject* rhs){ \
|
||||||
|
VoidP& voidp = PK_OBJ_GET(VoidP, lhs); \
|
||||||
|
i64 offset = CAST(i64, rhs); \
|
||||||
|
T* target = (T*)voidp.ptr; \
|
||||||
|
return vm->heap.gcnew<VoidP>(lhs->type, target - offset); \
|
||||||
|
}); \
|
||||||
|
vm->bind__repr__(type_t, [](VM* vm, PyObject* obj){ \
|
||||||
|
VoidP& self = _CAST(VoidP&, obj); \
|
||||||
|
return VAR(fmt("<", CNAME, "* at ", self.hex(), ">")); \
|
||||||
|
}); \
|
||||||
|
|
||||||
BIND_PRIMITIVE(char, "char")
|
BIND_PRIMITIVE(char, "char")
|
||||||
BIND_PRIMITIVE(unsigned char, "uchar")
|
BIND_PRIMITIVE(unsigned char, "uchar")
|
||||||
@ -262,9 +223,7 @@ void add_module_c(VM* vm){
|
|||||||
BIND_PRIMITIVE(double, "double")
|
BIND_PRIMITIVE(double, "double")
|
||||||
BIND_PRIMITIVE(bool, "bool")
|
BIND_PRIMITIVE(bool, "bool")
|
||||||
|
|
||||||
// add array type
|
#undef BIND_PRIMITIVE
|
||||||
CodeObject_ code = vm->compile(kPythonLibs["c"], "c.py", EXEC_MODE);
|
|
||||||
vm->_exec(code, mod);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
14
src/vm.cpp
14
src/vm.cpp
@ -79,13 +79,17 @@ namespace pkpy{
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VM::isinstance(PyObject* obj, Type cls_t){
|
bool VM::isinstance(PyObject* obj, Type base){
|
||||||
Type obj_t = PK_OBJ_GET(Type, _t(obj));
|
Type obj_t = PK_OBJ_GET(Type, _t(obj));
|
||||||
|
return issubclass(obj_t, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VM::issubclass(Type cls, Type base){
|
||||||
do{
|
do{
|
||||||
if(obj_t == cls_t) return true;
|
if(cls == base) return true;
|
||||||
Type base = _all_types[obj_t].base;
|
Type next = _all_types[cls].base;
|
||||||
if(base.index == -1) break;
|
if(next.index == -1) break;
|
||||||
obj_t = base;
|
cls = next;
|
||||||
}while(true);
|
}while(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,32 @@
|
|||||||
import c
|
import c
|
||||||
|
|
||||||
array = c.malloc(c.sizeof("int") * 10)
|
a = c.malloc(100)
|
||||||
|
c.free(a)
|
||||||
|
|
||||||
|
a = c.malloc(100)
|
||||||
|
c.memset(a, 0, 100)
|
||||||
|
b = c.malloc(100)
|
||||||
|
b = c.memcpy(b, a, 100)
|
||||||
|
|
||||||
|
bp = c.p_cast(a, c.int_p)
|
||||||
|
|
||||||
|
assert c.p_value(c.NULL) == 0
|
||||||
|
assert c.NULL == c.NULL
|
||||||
|
assert c.NULL != a
|
||||||
|
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
off = c.sizeof("int") * i
|
bp[i] = i
|
||||||
(array+off).write_int(i)
|
assert bp[i] == i
|
||||||
|
(bp+i).write(i)
|
||||||
|
assert (bp+i).read() == i
|
||||||
|
|
||||||
x = c.int_(0)
|
i = c.float_(10)
|
||||||
for i in range(10):
|
assert i.sizeof() == 4
|
||||||
off = c.sizeof("int") * i
|
j = i.copy()
|
||||||
i = (array+off).read_int()
|
assert i == j
|
||||||
x.write_int(x.read_int() + i)
|
assert i is not j
|
||||||
|
|
||||||
assert x.read_int() == (0+9)*10//2
|
####################
|
||||||
|
|
||||||
c.memset(array, 0, c.sizeof("int") * 10)
|
|
||||||
|
|
||||||
for i in range(10):
|
|
||||||
off = c.sizeof("int") * i
|
|
||||||
assert (array+off).read_char() == 0
|
|
||||||
|
|
||||||
array2 = c.malloc(c.sizeof("int") * 10)
|
|
||||||
c.memcpy(array2, array, c.sizeof("int") * 10)
|
|
||||||
for i in range(10):
|
|
||||||
off = c.sizeof("int") * i
|
|
||||||
assert (array+off).read_char() == 0
|
|
||||||
|
|
||||||
c.free(array)
|
|
||||||
c.free(array2)
|
|
||||||
|
|
||||||
class Vec2(c.struct):
|
class Vec2(c.struct):
|
||||||
def __new__(cls, x: float, y: float):
|
def __new__(cls, x: float, y: float):
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
import c
|
|
||||||
|
|
||||||
assert c.NULL == c.void_p(0)
|
|
||||||
# ------------------------------------------------
|
|
||||||
# 此处测试并不完全
|
|
||||||
c_void_1 = c.malloc(8)
|
|
||||||
c_void_1.read_bytes(5)
|
|
||||||
c_void_1.write_bytes(c_void_1.read_bytes(5))
|
|
||||||
# ------------------------------------------------
|
|
||||||
c_void_1 = c.malloc(32)
|
|
||||||
my_struct2 = c_void_1.read_struct(32)
|
|
||||||
assert my_struct2.sizeof() == 32
|
|
||||||
|
|
||||||
data_bytes = bytes([1,2,3])
|
|
||||||
my_struct4 = c.struct(data_bytes)
|
|
||||||
|
|
||||||
try:
|
|
||||||
c.struct(True)
|
|
||||||
raise Exception('c.struct 的构造方法未能触发 TypeError("expected int or bytes")')
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
c.struct(1,2,3)
|
|
||||||
raise Exception('c.struct 的构造方法未能触发 TypeError("expected 1 or 2 arguments")')
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
# ------------------------------------------------
|
|
||||||
my_struct1 = c.struct(16)
|
|
||||||
assert my_struct1.sizeof() == 16
|
|
||||||
|
|
||||||
# 对 c.struct 的 copy 方法的测试不完全
|
|
||||||
assert my_struct1.copy().sizeof() == 16
|
|
||||||
|
|
||||||
data_bytes = bytes([1,2,3])
|
|
||||||
my_struct4 = c.struct(data_bytes)
|
|
||||||
assert my_struct4.addr().read_bytes(
|
|
||||||
my_struct4.sizeof()
|
|
||||||
) == data_bytes
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
|
||||||
# 此处测试并不完全
|
|
||||||
c_void_1 = c.malloc(16)
|
|
||||||
my_struct1 = c.struct(16)
|
|
||||||
c_void_1.write_struct(my_struct1)
|
|
||||||
assert c_void_1.read_struct(16) == my_struct1
|
|
||||||
|
|
||||||
from c import array, int_, NULL
|
|
||||||
|
|
||||||
assert NULL._value == 0
|
|
||||||
|
|
||||||
a = array(10, item_size=4)
|
|
||||||
assert a.item_count == 10
|
|
||||||
assert a.item_size == 4
|
|
||||||
|
|
||||||
a[4] = int_(123)
|
|
||||||
assert a[4] == int_(123)
|
|
Loading…
x
Reference in New Issue
Block a user