mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20: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); \
|
||||
}); \
|
||||
|
||||
#define PY_POINTER_LIKE(wT) \
|
||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ \
|
||||
#define PY_POINTER_SETGETITEM(wT) \
|
||||
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); \
|
||||
if(!vm->isinstance(_1, wT::_type(vm))) return vm->NotImplemented; \
|
||||
wT& other = _CAST(wT&, _1); \
|
||||
return VAR(self._() == other._()); \
|
||||
i64 i = CAST(i64, _1); \
|
||||
return VAR(self._()[i]); \
|
||||
}); \
|
||||
vm->bind__hash__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){ \
|
||||
wT& self = _CAST(wT&, obj); \
|
||||
return reinterpret_cast<i64>(self._()); \
|
||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1, PyObject* _2){ \
|
||||
wT& self = _CAST(wT&, _0); \
|
||||
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
|
@ -29,9 +29,6 @@ namespace pkpy {
|
||||
|
||||
#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{
|
||||
PY_CLASS(VoidP, c, void_p)
|
||||
|
||||
@ -58,6 +55,10 @@ struct VoidP{
|
||||
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||
};
|
||||
|
||||
inline PyObject* py_var(VM* vm, void* p){
|
||||
return VAR_T(VoidP, p);
|
||||
}
|
||||
|
||||
struct C99Struct{
|
||||
PY_CLASS(C99Struct, c, struct)
|
||||
|
||||
@ -81,33 +82,14 @@ struct C99Struct{
|
||||
}
|
||||
|
||||
C99Struct(const C99Struct& other): C99Struct(other.p, other.size){}
|
||||
|
||||
~C99Struct(){ if(p!=_inlined) free(p); }
|
||||
|
||||
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_<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>
|
||||
T to_void_p(VM* vm, PyObject* var){
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <random>
|
||||
#include <bitset>
|
||||
|
||||
#define PK_VERSION "1.2.3"
|
||||
#define PK_VERSION "1.2.4"
|
||||
|
||||
#include "config.h"
|
||||
#include "export.h"
|
||||
|
@ -167,7 +167,8 @@ public:
|
||||
PyObject* py_iter(PyObject* obj);
|
||||
|
||||
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);
|
||||
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 free(ptr: 'void_p') -> None: ...
|
||||
def sizeof(type: str) -> int: ...
|
||||
def memset(ptr: 'void_p', value: int, 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:
|
||||
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 __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 __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
|
||||
def _value(self) -> int: ...
|
||||
|
||||
def read_char(self) -> int: ...
|
||||
def read_uchar(self) -> int: ...
|
||||
def read_short(self) -> int: ...
|
||||
def read_ushort(self) -> int: ...
|
||||
def read_int(self) -> int: ...
|
||||
def read_uint(self) -> int: ...
|
||||
def read_long(self) -> int: ...
|
||||
def read_ulong(self) -> int: ...
|
||||
def read_longlong(self) -> int: ...
|
||||
def read_ulonglong(self) -> int: ...
|
||||
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 char_p(Pointer[int]): pass
|
||||
class uchar_p(Pointer[int]): pass
|
||||
class short_p(Pointer[int]): pass
|
||||
class ushort_p(Pointer[int]): pass
|
||||
class int_p(Pointer[int]): pass
|
||||
class uint_p(Pointer[int]): pass
|
||||
class long_p(Pointer[int]): pass
|
||||
class ulong_p(Pointer[int]): pass
|
||||
class longlong_p(Pointer[int]): pass
|
||||
class ulonglong_p(Pointer[int]): pass
|
||||
class float_p(Pointer[float]): pass
|
||||
class double_p(Pointer[float]): pass
|
||||
class bool_p(Pointer[bool]): pass
|
||||
|
||||
class struct:
|
||||
@overload
|
||||
def __init__(self, size: int): ...
|
||||
@overload
|
||||
def __init__(self, buffer: bytes): ...
|
||||
|
||||
def addr(self) -> 'void_p': ...
|
||||
def copy(self) -> 'struct': ...
|
||||
def sizeof(self) -> int: ...
|
||||
@ -79,7 +68,6 @@ class struct:
|
||||
def read_double(self, offset=0) -> float: ...
|
||||
def read_bool(self, offset=0) -> bool: ...
|
||||
def read_void_p(self, offset=0) -> 'void_p': ...
|
||||
|
||||
def write_char(self, value: int, offset=0) -> None: ...
|
||||
def write_uchar(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 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]):
|
||||
def to_struct(self) -> struct: ...
|
||||
@classmethod
|
||||
def from_struct(cls, s: struct) -> T: ...
|
||||
|
||||
def addr(self) -> '_PointerLike[T]': ...
|
||||
def sizeof(self) -> int: ...
|
||||
def addr(self) -> 'Pointer[T]': ...
|
||||
def copy(self) -> T: ...
|
||||
def sizeof(self) -> int: ...
|
||||
def __eq__(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/str.h"
|
||||
|
||||
namespace pkpy{
|
||||
|
||||
@ -10,26 +9,19 @@ namespace pkpy{
|
||||
return vm->heap.gcnew<VoidP>(cls, reinterpret_cast<void*>(addr));
|
||||
});
|
||||
|
||||
vm->bind_method<0>(type, "hex", [](VM* vm, ArgsView args){
|
||||
VoidP& self = _CAST(VoidP&, args[0]);
|
||||
return VAR(self.hex());
|
||||
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__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
||||
VoidP& self = _CAST(VoidP&, obj);
|
||||
std::stringstream ss;
|
||||
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));
|
||||
return VAR(fmt("<void* at ", self.hex(), ">"));
|
||||
});
|
||||
|
||||
#define BIND_CMP(name, op) \
|
||||
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)); \
|
||||
});
|
||||
|
||||
@ -40,81 +32,14 @@ namespace pkpy{
|
||||
BIND_CMP(__ge__, >=)
|
||||
|
||||
#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){
|
||||
vm->bind_constructor<2>(type, [](VM* vm, ArgsView args){
|
||||
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);
|
||||
}
|
||||
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){
|
||||
@ -161,7 +86,6 @@ namespace pkpy{
|
||||
*(T*)ptr = CAST(T, args[1]); \
|
||||
return vm->None; \
|
||||
});
|
||||
|
||||
BIND_SETGET(char, "char")
|
||||
BIND_SETGET(unsigned char, "uchar")
|
||||
BIND_SETGET(short, "short")
|
||||
@ -177,22 +101,6 @@ namespace pkpy{
|
||||
BIND_SETGET(bool, "bool")
|
||||
BIND_SETGET(void*, "void_p")
|
||||
#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){
|
||||
@ -225,28 +133,81 @@ void add_module_c(VM* vm){
|
||||
});
|
||||
#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);
|
||||
C99Struct::register_class(vm, mod);
|
||||
mod->attr().set("NULL", VAR_T(VoidP, nullptr));
|
||||
|
||||
add_refl_type("void_p", sizeof(void*));
|
||||
PyObject* void_p_t = mod->attr("void_p");
|
||||
vm->bind(mod, "p_cast(ptr: 'void_p', cls: type[T]) -> T", [](VM* vm, ArgsView args){
|
||||
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_func<1>(mod, name "_", [](VM* vm, ArgsView args){ \
|
||||
vm->bind(mod, "p_value(ptr: 'void_p') -> int", [](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]); \
|
||||
return VAR_T(C99Struct, &val, sizeof(T)); \
|
||||
}); \
|
||||
add_refl_type(name, sizeof(T)); \
|
||||
mod->attr().set(name "_p", void_p_t); \
|
||||
type = vm->new_type_object(mod, CNAME "_p", VoidP::_type(vm)); \
|
||||
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(unsigned char, "uchar")
|
||||
@ -262,9 +223,7 @@ void add_module_c(VM* vm){
|
||||
BIND_PRIMITIVE(double, "double")
|
||||
BIND_PRIMITIVE(bool, "bool")
|
||||
|
||||
// add array type
|
||||
CodeObject_ code = vm->compile(kPythonLibs["c"], "c.py", EXEC_MODE);
|
||||
vm->_exec(code, mod);
|
||||
#undef BIND_PRIMITIVE
|
||||
}
|
||||
|
||||
} // namespace pkpy
|
14
src/vm.cpp
14
src/vm.cpp
@ -79,13 +79,17 @@ namespace pkpy{
|
||||
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));
|
||||
return issubclass(obj_t, base);
|
||||
}
|
||||
|
||||
bool VM::issubclass(Type cls, Type base){
|
||||
do{
|
||||
if(obj_t == cls_t) return true;
|
||||
Type base = _all_types[obj_t].base;
|
||||
if(base.index == -1) break;
|
||||
obj_t = base;
|
||||
if(cls == base) return true;
|
||||
Type next = _all_types[cls].base;
|
||||
if(next.index == -1) break;
|
||||
cls = next;
|
||||
}while(true);
|
||||
return false;
|
||||
}
|
||||
|
@ -1,33 +1,32 @@
|
||||
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):
|
||||
off = c.sizeof("int") * i
|
||||
(array+off).write_int(i)
|
||||
bp[i] = i
|
||||
assert bp[i] == i
|
||||
(bp+i).write(i)
|
||||
assert (bp+i).read() == i
|
||||
|
||||
x = c.int_(0)
|
||||
for i in range(10):
|
||||
off = c.sizeof("int") * i
|
||||
i = (array+off).read_int()
|
||||
x.write_int(x.read_int() + i)
|
||||
i = c.float_(10)
|
||||
assert i.sizeof() == 4
|
||||
j = i.copy()
|
||||
assert i == j
|
||||
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):
|
||||
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