This commit is contained in:
blueloveTH 2023-09-29 18:43:59 +08:00
parent bf1c1bd678
commit 6062e34a29
10 changed files with 167 additions and 355 deletions

View File

@ -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

View File

@ -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){

View File

@ -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"

View File

@ -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);

View File

@ -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: ...

View File

@ -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

View File

@ -1,5 +1,4 @@
#include "pocketpy/cffi.h" #include "pocketpy/cffi.h"
#include "pocketpy/str.h"
namespace pkpy{ namespace pkpy{
@ -10,27 +9,20 @@ 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)); \
}); });
BIND_CMP(__eq__, ==) BIND_CMP(__eq__, ==)
@ -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]);
T val = CAST(T, args[0]); \ return VAR(reinterpret_cast<i64>(ptr.ptr));
return VAR_T(C99Struct, &val, sizeof(T)); \ });
}); \
add_refl_type(name, sizeof(T)); \ vm->bind(mod, "pp_deref(ptr: Tp) -> Tp", [](VM* vm, ArgsView args){
mod->attr().set(name "_p", void_p_t); \ 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)); \
}); \
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(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

View File

@ -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;
} }

View File

@ -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):
@ -50,4 +49,4 @@ class Vec2(c.struct):
a = Vec2(1, 2) a = Vec2(1, 2)
assert isinstance(a, c.struct) assert isinstance(a, c.struct)
assert type(a) is Vec2 assert type(a) is Vec2
assert repr(a) == "Vec2(1.0, 2.0)" assert repr(a) == "Vec2(1.0, 2.0)"

View File

@ -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)