diff --git a/include/pocketpy/bindings.h b/include/pocketpy/bindings.h index 18655866..8670300d 100644 --- a/include/pocketpy/bindings.h +++ b/include/pocketpy/bindings.h @@ -114,17 +114,36 @@ void _bind(VM* vm, PyObject* obj, const char* sig, Ret(T::*func)(Params...)){ }); #define PY_STRUCT_LIKE_OBJECT(T) \ - static_assert(std::is_trivially_copyable::value); \ - vm->bind_func<1>(type, "__from_struct__", [](VM* vm, ArgsView args){ \ - C99Struct& s = CAST(C99Struct&, args[0]); \ - if(s.size != sizeof(T)) vm->ValueError("size mismatch"); \ + static_assert(std::is_trivially_copyable::value); \ + vm->bind_func<1>(type, "from_struct", [](VM* vm, ArgsView args){ \ + C99Struct& s = CAST(C99Struct&, args[0]); \ + if(s.size != sizeof(T)) vm->ValueError("size mismatch"); \ PyObject* obj = vm->heap.gcnew(T::_type(vm)); \ memcpy(&_CAST(T&, obj), s.p, sizeof(T)); \ return obj; \ }); \ - vm->bind_method<0>(type, "__to_struct__", [](VM* vm, ArgsView args){ \ + vm->bind_method<0>(type, "to_struct", [](VM* vm, ArgsView args){ \ T& self = _CAST(T&, args[0]); \ return VAR_T(C99Struct, &self, sizeof(T)); \ - }); + }); \ + vm->bind_method<0>(type, "addr", [](VM* vm, ArgsView args){ \ + T& self = _CAST(T&, args[0]); \ + return VAR_T(VoidP, &self); \ + }); \ + vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){ \ + T& self = _CAST(T&, args[0]); \ + return VAR_T(T, self); \ + }); \ + vm->bind_method<0>(type, "sizeof", [](VM* vm, ArgsView args){ \ + return VAR(sizeof(T)); \ + }); \ + vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ \ + T& self = _CAST(T&, _0); \ + if(!vm->isinstance(_1, T::_type(vm))){ \ + return vm->NotImplemented; \ + } \ + T& other = _CAST(T&, _1); \ + return VAR(self == other); \ + }); \ } // namespace pkpy \ No newline at end of file diff --git a/include/pocketpy/str.h b/include/pocketpy/str.h index e89ee5bc..2f387aa1 100644 --- a/include/pocketpy/str.h +++ b/include/pocketpy/str.h @@ -192,9 +192,6 @@ const StrName __package__ = StrName::get("__package__"); const StrName __path__ = StrName::get("__path__"); const StrName __class__ = StrName::get("__class__"); -const StrName __to_struct__ = StrName::get("__to_struct__"); -const StrName __from_struct__ = StrName::get("__from_struct__"); - const StrName pk_id_add = StrName::get("add"); const StrName pk_id_set = StrName::get("set"); const StrName pk_id_eval = StrName::get("eval"); diff --git a/include/typings/c.pyi b/include/typings/c.pyi index 92f69c65..e057280f 100644 --- a/include/typings/c.pyi +++ b/include/typings/c.pyi @@ -128,5 +128,18 @@ class array(struct): def __setitem__(self, index: int, value: struct) -> None: ... def __len__(self) -> int: ... -def to_struct(obj) -> struct: ... -def from_struct(T: type, obj: struct): ... \ No newline at end of file +from typing import Generic, TypeVar + +T = TypeVar('T') + +class _struct_like(Generic[T]): + def to_struct(self) -> struct: ... + @classmethod + def from_struct(cls, s: struct) -> T: ... + + def addr(self) -> void_p: ... + def sizeof(self) -> int: ... + def copy(self) -> T: ... + def __eq__(self, other: T) -> bool: ... + def __ne__(self, other: T) -> bool: ... + diff --git a/include/typings/linalg.pyi b/include/typings/linalg.pyi index 2cc0c62f..a2377c0f 100644 --- a/include/typings/linalg.pyi +++ b/include/typings/linalg.pyi @@ -1,12 +1,11 @@ from typing import overload -from c import float_p +from c import _struct_like -class vec2: +class vec2(_struct_like['vec2']): x: float y: float def __init__(self, x: float, y: float) -> None: ... - def copy(self) -> vec2: ... def __add__(self, other: vec2) -> vec2: ... def __sub__(self, other: vec2) -> vec2: ... def __mul__(self, other: float) -> vec2: ... @@ -18,15 +17,13 @@ class vec2: def normalize(self) -> vec2: ... def rotate(self, radians: float) -> vec2: ... def rotate_(self, radians: float) -> None: ... - def addr(self) -> float_p: ... -class vec3: +class vec3(_struct_like['vec3']): x: float y: float z: float def __init__(self, x: float, y: float, z: float) -> None: ... - def copy(self) -> vec3: ... def __add__(self, other: vec3) -> vec3: ... def __sub__(self, other: vec3) -> vec3: ... def __mul__(self, other: float) -> vec3: ... @@ -36,16 +33,14 @@ class vec3: def length(self) -> float: ... def length_squared(self) -> float: ... def normalize(self) -> vec3: ... - def addr(self) -> float_p: ... -class vec4: +class vec4(_struct_like['vec4']): x: float y: float z: float w: float def __init__(self, x: float, y: float, z: float, w: float) -> None: ... - def copy(self) -> vec4: ... def __add__(self, other: vec4) -> vec4: ... def __sub__(self, other: vec4) -> vec4: ... def __mul__(self, other: float) -> vec4: ... @@ -54,9 +49,8 @@ class vec4: def length(self) -> float: ... def length_squared(self) -> float: ... def normalize(self) -> vec4: ... - def addr(self) -> float_p: ... -class mat3x3: +class mat3x3(_struct_like['mat3x3']): _11: float _12: float _13: float @@ -78,7 +72,6 @@ class mat3x3: def set_ones(self) -> None: ... def set_identity(self) -> None: ... - def copy(self) -> mat3x3: ... def determinant(self) -> float: ... def transpose(self) -> mat3x3: ... diff --git a/python/c.py b/python/c.py index 4e5ad1b9..e876c0be 100644 --- a/python/c.py +++ b/python/c.py @@ -18,8 +18,8 @@ class array(struct): 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.size() != self.item_size: - raise ValueError(f"array item size mismatch: {value.size()} != {self.item_size}") + 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) diff --git a/src/cffi.cpp b/src/cffi.cpp index ed5f852a..837b94f3 100644 --- a/src/cffi.cpp +++ b/src/cffi.cpp @@ -130,7 +130,7 @@ namespace pkpy{ return VAR_T(VoidP, self.p); }); - vm->bind_method<0>(type, "size", [](VM* vm, ArgsView args){ + vm->bind_method<0>(type, "sizeof", [](VM* vm, ArgsView args){ C99Struct& self = _CAST(C99Struct&, args[0]); return VAR(self.size); }); @@ -234,15 +234,6 @@ void add_module_c(VM* vm){ return vm->None; }); - vm->bind_func<1>(mod, "to_struct", [](VM* vm, ArgsView args){ - return vm->call_method(args[0], __to_struct__); - }); - - vm->bind_func<2>(mod, "from_struct", [](VM* vm, ArgsView args){ - PyObject* f = vm->getattr(args[0], __from_struct__); - return vm->call(f, args[1]); - }); - VoidP::register_class(vm, mod); C99Struct::register_class(vm, mod); mod->attr().set("NULL", VAR_T(VoidP, nullptr)); diff --git a/src/linalg.cpp b/src/linalg.cpp index aedb049c..62b2bb38 100644 --- a/src/linalg.cpp +++ b/src/linalg.cpp @@ -2,12 +2,6 @@ namespace pkpy{ -#define BIND_VEC_ADDR(D) \ - vm->bind_method<0>(type, "addr", [](VM* vm, ArgsView args){ \ - PyVec##D& self = _CAST(PyVec##D&, args[0]); \ - return VAR_T(VoidP, &self.x); \ - }); - #define BIND_VEC_VEC_OP(D, name, op) \ vm->bind_method<1>(type, #name, [](VM* vm, ArgsView args){ \ PyVec##D& self = _CAST(PyVec##D&, args[0]); \ @@ -68,11 +62,6 @@ namespace pkpy{ return VAR(ss.str()); }); - vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){ - PyVec2& self = _CAST(PyVec2&, args[0]); - return VAR_T(PyVec2, self); - }); - vm->bind_method<1>(type, "rotate", [](VM* vm, ArgsView args){ Vec2 self = _CAST(PyVec2&, args[0]); float radian = CAST(f64, args[1]); @@ -97,13 +86,11 @@ namespace pkpy{ return vm->None; }); - BIND_VEC_ADDR(2) BIND_VEC_VEC_OP(2, __add__, +) BIND_VEC_VEC_OP(2, __sub__, -) BIND_VEC_FLOAT_OP(2, __mul__, *) BIND_VEC_FLOAT_OP(2, __rmul__, *) BIND_VEC_FLOAT_OP(2, __truediv__, /) - BIND_VEC_VEC_OP(2, __eq__, ==) BIND_VEC_FIELD(2, x) BIND_VEC_FIELD(2, y) BIND_VEC_FUNCTION_1(2, dot) @@ -135,18 +122,11 @@ namespace pkpy{ return VAR(ss.str()); }); - vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){ - PyVec3& self = _CAST(PyVec3&, args[0]); - return VAR_T(PyVec3, self); - }); - - BIND_VEC_ADDR(3) BIND_VEC_VEC_OP(3, __add__, +) BIND_VEC_VEC_OP(3, __sub__, -) BIND_VEC_FLOAT_OP(3, __mul__, *) BIND_VEC_FLOAT_OP(3, __rmul__, *) BIND_VEC_FLOAT_OP(3, __truediv__, /) - BIND_VEC_VEC_OP(3, __eq__, ==) BIND_VEC_FIELD(3, x) BIND_VEC_FIELD(3, y) BIND_VEC_FIELD(3, z) @@ -180,18 +160,11 @@ namespace pkpy{ return VAR(ss.str()); }); - vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){ - PyVec4& self = _CAST(PyVec4&, args[0]); - return VAR_T(PyVec4, self); - }); - - BIND_VEC_ADDR(4) BIND_VEC_VEC_OP(4, __add__, +) BIND_VEC_VEC_OP(4, __sub__, -) BIND_VEC_FLOAT_OP(4, __mul__, *) BIND_VEC_FLOAT_OP(4, __rmul__, *) BIND_VEC_FLOAT_OP(4, __truediv__, /) - BIND_VEC_VEC_OP(4, __eq__, ==) BIND_VEC_FIELD(4, x) BIND_VEC_FIELD(4, y) BIND_VEC_FIELD(4, z) @@ -266,11 +239,6 @@ namespace pkpy{ return VAR(ss.str()); }); - vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){ - PyMat3x3& self = _CAST(PyMat3x3&, args[0]); - return VAR_T(PyMat3x3, self); - }); - vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj, PyObject* index){ PyMat3x3& self = _CAST(PyMat3x3&, obj); Tuple& t = CAST(Tuple&, index); @@ -369,15 +337,6 @@ namespace pkpy{ return vm->NotImplemented; }); - vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ - PyMat3x3& self = _CAST(PyMat3x3&, _0); - if(is_non_tagged_type(_1, PyMat3x3::_type(vm))){ - PyMat3x3& other = _CAST(PyMat3x3&, _1); - return VAR(self == other); - } - return vm->NotImplemented; - }); - vm->bind_method<0>(type, "determinant", [](VM* vm, ArgsView args){ PyMat3x3& self = _CAST(PyMat3x3&, args[0]); return VAR(self.determinant()); diff --git a/tests/80_linalg.py b/tests/80_linalg.py index a97c7fe5..0b6eae2c 100644 --- a/tests/80_linalg.py +++ b/tests/80_linalg.py @@ -474,6 +474,7 @@ temp_vec2 = test_mat_copy.transform_vector(test_vec2_copy) import c a = vec2(1, 2) -b = c.to_struct(a) -assert b.size() == 8 -assert c.from_struct(vec2, b) == a \ No newline at end of file +b = a.to_struct() +assert a.sizeof() == 8 +assert b.sizeof() == 8 +assert vec2.from_struct(b) == a diff --git a/tests/99_cffi_2.py b/tests/99_cffi_2.py index 3f87c079..8737d33d 100644 --- a/tests/99_cffi_2.py +++ b/tests/99_cffi_2.py @@ -9,7 +9,7 @@ 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.size() == 32 +assert my_struct2.sizeof() == 32 data_bytes = bytes([1,2,3]) my_struct4 = c.struct(data_bytes) @@ -27,15 +27,15 @@ except TypeError: pass # ------------------------------------------------ my_struct1 = c.struct(16) -assert my_struct1.size() == 16 +assert my_struct1.sizeof() == 16 # 对 c.struct 的 copy 方法的测试不完全 -assert my_struct1.copy().size() == 16 +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.size() + my_struct4.sizeof() ) == data_bytes