blueloveTH пре 2 година
родитељ
комит
5a42d35f9d
10 измењених фајлова са 156 додато и 185 уклоњено
  1. 0 20
      include/pocketpy/cffi.h
  2. 16 11
      include/pocketpy/linalg.h
  3. 25 29
      include/typings/c.pyi
  4. 27 0
      python/c.py
  5. 2 2
      python/collections.py
  6. 51 94
      src/cffi.cpp
  7. 12 0
      src/pocketpy.cpp
  8. 3 8
      tests/80_c.py
  9. 4 1
      tests/80_linalg.py
  10. 16 20
      tests/99_cffi_2.py

+ 0 - 20
include/pocketpy/cffi.h

@@ -29,8 +29,6 @@ namespace pkpy {
 
 #define VAR_T(T, ...) vm->heap.gcnew<T>(T::_type(vm), __VA_ARGS__)
 
-int c99_sizeof(VM*, const Str&);
-
 inline PyObject* py_var(VM* vm, void* p);
 inline PyObject* py_var(VM* vm, char* p);
 
@@ -80,13 +78,6 @@ struct C99Struct{
         }
     }
 
-    template<typename T>
-    C99Struct(std::monostate _, const T& data): C99Struct(sizeof(T)){
-        static_assert(is_pod<T>::value);
-        static_assert(!std::is_pointer_v<T>);
-        memcpy(p, &data, this->size);
-    }
-
     C99Struct(void* p, int size): C99Struct(size){
         if(p != nullptr) memcpy(this->p, p, size);
     }
@@ -120,17 +111,6 @@ inline void add_refl_type(std::string_view name, size_t size){
     _refl_types[name] = std::move(type);
 }
 
-struct C99ReflType final: ReflType{
-    PY_CLASS(C99ReflType, c, _refl)
-
-    C99ReflType(const ReflType& type){
-        this->name = type.name;
-        this->size = type.size;
-    }
-
-    static void _register(VM* vm, PyObject* mod, PyObject* type);
-};
-
 static_assert(sizeof(Py_<C99Struct>) <= 64);
 static_assert(sizeof(Py_<Tuple>) <= 64);
 

+ 16 - 11
include/pocketpy/linalg.h

@@ -4,14 +4,13 @@
 
 namespace pkpy{
 
-static constexpr float kEpsilon = 1e-4f;
-inline static bool isclose(float a, float b){ return fabsf(a - b) < kEpsilon; }
+inline bool isclose(float a, float b){ return fabsf(a - b) < 1e-4f; }
 
 struct Vec2{
     float x, y;
     Vec2() : x(0.0f), y(0.0f) {}
     Vec2(float x, float y) : x(x), y(y) {}
-    Vec2(const Vec2& v) : x(v.x), y(v.y) {}
+    Vec2(const Vec2& v) = default;
 
     Vec2 operator+(const Vec2& v) const { return Vec2(x + v.x, y + v.y); }
     Vec2& operator+=(const Vec2& v) { x += v.x; y += v.y; return *this; }
@@ -35,7 +34,7 @@ struct Vec3{
     float x, y, z;
     Vec3() : x(0.0f), y(0.0f), z(0.0f) {}
     Vec3(float x, float y, float z) : x(x), y(y), z(z) {}
-    Vec3(const Vec3& v) : x(v.x), y(v.y), z(v.z) {}
+    Vec3(const Vec3& v) = default;
 
     Vec3 operator+(const Vec3& v) const { return Vec3(x + v.x, y + v.y, z + v.z); }
     Vec3& operator+=(const Vec3& v) { x += v.x; y += v.y; z += v.z; return *this; }
@@ -59,7 +58,7 @@ struct Vec4{
     float x, y, z, w;
     Vec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {}
     Vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
-    Vec4(const Vec4& v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
+    Vec4(const Vec4& v) = default;
 
     Vec4 operator+(const Vec4& v) const { return Vec4(x + v.x, y + v.y, z + v.z, w + v.w); }
     Vec4& operator+=(const Vec4& v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
@@ -96,6 +95,8 @@ struct Mat3x3{
         : _11(_11), _12(_12), _13(_13)
         , _21(_21), _22(_22), _23(_23)
         , _31(_31), _32(_32), _33(_33) {}
+    
+    Mat3x3(const Mat3x3& other) = default;
 
     void set_zeros(){ for (int i=0; i<9; ++i) v[i] = 0.0f; }
     void set_ones(){ for (int i=0; i<9; ++i) v[i] = 1.0f; }
@@ -208,7 +209,7 @@ struct Mat3x3{
 
     bool inverse(Mat3x3& ret) const{
         float det = determinant();
-        if (fabsf(det) < kEpsilon) return false;
+        if (isclose(det, 0)) return false;
         float inv_det = 1.0f / det;
         ret._11 = (_22 * _33 - _23 * _32) * inv_det;
         ret._12 = (_13 * _32 - _12 * _33) * inv_det;
@@ -233,7 +234,7 @@ struct Mat3x3{
 
     bool is_affine() const{
         float det = _11 * _22 - _12 * _21;
-        if(fabsf(det) < kEpsilon) return false;
+        if(!isclose(det, 0)) return false;
         return _31 == 0.0f && _32 == 0.0f && _33 == 1.0f;
     }
 
@@ -274,7 +275,7 @@ struct PyVec2: Vec2 {
 
     PyVec2() : Vec2() {}
     PyVec2(const Vec2& v) : Vec2(v) {}
-    PyVec2(const PyVec2& v) : Vec2(v) {}
+    PyVec2(const PyVec2& v) = default;
 
     static void _register(VM* vm, PyObject* mod, PyObject* type);
 };
@@ -284,7 +285,7 @@ struct PyVec3: Vec3 {
 
     PyVec3() : Vec3() {}
     PyVec3(const Vec3& v) : Vec3(v) {}
-    PyVec3(const PyVec3& v) : Vec3(v) {}
+    PyVec3(const PyVec3& v) = default;
 
     static void _register(VM* vm, PyObject* mod, PyObject* type);
 };
@@ -294,7 +295,7 @@ struct PyVec4: Vec4{
 
     PyVec4(): Vec4(){}
     PyVec4(const Vec4& v): Vec4(v){}
-    PyVec4(const PyVec4& v): Vec4(v){}
+    PyVec4(const PyVec4& v) = default;
 
     static void _register(VM* vm, PyObject* mod, PyObject* type);
 };
@@ -304,7 +305,7 @@ struct PyMat3x3: Mat3x3{
 
     PyMat3x3(): Mat3x3(){}
     PyMat3x3(const Mat3x3& other): Mat3x3(other){}
-    PyMat3x3(const PyMat3x3& other): Mat3x3(other){}
+    PyMat3x3(const PyMat3x3& other) = default;
 
     static void _register(VM* vm, PyObject* mod, PyObject* type);
 };
@@ -340,5 +341,9 @@ inline void add_module_linalg(VM* vm){
 }
 
 static_assert(sizeof(Py_<PyMat3x3>) <= 64);
+static_assert(std::is_trivially_copyable<PyVec2>::value);
+static_assert(std::is_trivially_copyable<PyVec3>::value);
+static_assert(std::is_trivially_copyable<PyVec4>::value);
+static_assert(std::is_trivially_copyable<PyMat3x3>::value);
 
 }   // namespace pkpy

+ 25 - 29
include/typings/c.pyi

@@ -3,15 +3,9 @@ from typing import overload
 def malloc(size: int) -> 'void_p': ...
 def free(ptr: 'void_p') -> None: ...
 def sizeof(type: str) -> int: ...
-def refl(name: str) -> '_refl': ...
 def memset(ptr: 'void_p', value: int, size: int) -> None: ...
 def memcpy(dst: 'void_p', src: 'void_p', size: int) -> None: ...
 
-class _refl:
-    def __call__(self) -> 'struct': ...
-    def name(self) -> str: ...
-    def size(self) -> int: ...
-
 class void_p:
     def __add__(self, i: int) -> 'void_p': ...
     def __sub__(self, i: int) -> 'void_p': ...
@@ -37,7 +31,7 @@ class void_p:
     def read_bool(self) -> bool: ...
     def read_void_p(self) -> 'void_p': ...
     def read_bytes(self, size: int) -> bytes: ...
-    def read_struct(self, type: str) -> 'struct': ...
+    def read_struct(self, size: int) -> 'struct': ...
 
     def write_char(self, value: int) -> None: ...
     def write_uchar(self, value: int) -> None: ...
@@ -60,11 +54,7 @@ class struct:
     @overload
     def __init__(self, size: int): ...
     @overload
-    def __init__(self, p: 'void_p', size: int): ...
-    @overload
-    def __init__(self, s: str): ...
-    @overload
-    def __init__(self, b: bytes): ...
+    def __init__(self, buffer: bytes): ...
 
     def addr(self) -> 'void_p': ...
     def copy(self) -> 'struct': ...
@@ -72,9 +62,6 @@ class struct:
     def __eq__(self, other: 'struct') -> bool: ...
     def __ne__(self, other: 'struct') -> bool: ...
 
-    def to_string(self) -> str: ...
-    def to_bytes(self) -> bytes: ...
-
     def read_char(self, offset=0) -> int: ...
     def read_uchar(self, offset=0) -> int: ...
     def read_short(self, offset=0) -> int: ...
@@ -105,19 +92,19 @@ class struct:
     def write_bool(self, value: bool, offset=0) -> None: ...
     def write_void_p(self, value: 'void_p', offset=0) -> None: ...
 
-char_ = refl("char")
-uchar_ = refl("uchar")
-short_ = refl("short")
-ushort_ = refl("ushort")
-int_ = refl("int")
-uint_ = refl("uint")
-long_ = refl("long")
-ulong_ = refl("ulong")
-longlong_ = refl("longlong")
-ulonglong_ = refl("ulonglong")
-float_ = refl("float")
-double_ = refl("double")
-bool_ = refl("bool")
+def char_(val: int) -> struct: ...
+def uchar_(val: int) -> struct: ...
+def short_(val: int) -> struct: ...
+def ushort_(val: int) -> struct: ...
+def int_(val: int) -> struct: ...
+def uint_(val: int) -> struct: ...
+def long_(val: int) -> struct: ...
+def ulong_(val: int) -> struct: ...
+def longlong_(val: int) -> struct: ...
+def ulonglong_(val: int) -> struct: ...
+def float_(val: float) -> struct: ...
+def double_(val: float) -> struct: ...
+def bool_(val: bool) -> struct: ...
 
 char_p = void_p
 uchar_p = void_p
@@ -131,4 +118,13 @@ longlong_p = void_p
 ulonglong_p = void_p
 float_p = void_p
 double_p = void_p
-bool_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: ...

+ 27 - 0
python/c.py

@@ -0,0 +1,27 @@
+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.size() != self.item_size:
+            raise ValueError(f"array item size mismatch: {value.size()} != {self.item_size}")
+        p = self.addr() + self.item_size * index
+        p.write_struct(value)
+
+    def __len__(self) -> int:
+        return self.item_count

+ 2 - 2
python/collections.py

@@ -156,5 +156,5 @@ class defaultdict:
     def items(self):
         return self._a.items()
 
-    def pop(self, key):
-        return self._a.pop(key)
+    def pop(self, *args):
+        return self._a.pop(*args)

+ 51 - 94
src/cffi.cpp

@@ -100,33 +100,33 @@ namespace pkpy{
     }
 
     void C99Struct::_register(VM* vm, PyObject* mod, PyObject* type){
-        vm->bind_constructor<-1>(type, [](VM* vm, ArgsView args){
+        vm->bind_constructor<2>(type, [](VM* vm, ArgsView args){
             Type cls = PK_OBJ_GET(Type, args[0]);
-            if(args.size() == 1+1){
-                if(is_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_str)){
-                    const Str& s = _CAST(Str&, args[1]);
-                    return vm->heap.gcnew<C99Struct>(cls, (void*)s.data, s.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, str or bytes");
-                return vm->None;
+            if(is_int(args[1])){
+                int size = _CAST(int, args[1]);
+                return vm->heap.gcnew<C99Struct>(cls, size);
             }
-            if(args.size() == 1+2){
-                void* p = CAST(void*, args[1]);
-                int size = CAST(int, args[2]);
-                return vm->heap.gcnew<C99Struct>(cls, p, 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 1 or 2 arguments");
+            vm->TypeError("expected int or bytes");
             return vm->None;
         });
 
+        vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
+            C99Struct& self = _CAST(C99Struct&, obj);
+            std::stringstream ss;
+            ss << "<struct object of " << self.size << " bytes>";
+            return VAR(ss.str());
+        });
+
+        vm->bind__hash__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
+            C99Struct& self = _CAST(C99Struct&, obj);
+            std::string_view view((char*)self.p, self.size);
+            return (i64)std::hash<std::string_view>()(view);
+        });
+
         vm->bind_method<0>(type, "addr", [](VM* vm, ArgsView args){
             C99Struct& self = _CAST(C99Struct&, args[0]);
             return VAR_T(VoidP, self.p);
@@ -142,18 +142,6 @@ namespace pkpy{
             return VAR_T(C99Struct, self);
         });
 
-        vm->bind_method<0>(type, "to_string", [](VM* vm, ArgsView args){
-            C99Struct& self = _CAST(C99Struct&, args[0]);
-            return VAR(Str(self.p, self.size));
-        });
-
-        vm->bind_method<0>(type, "to_bytes", [](VM* vm, ArgsView args){
-            C99Struct& self = _CAST(C99Struct&, args[0]);
-            std::vector<char> buffer(self.size);
-            memcpy(buffer.data(), self.p, self.size);
-            return VAR(Bytes(std::move(buffer)));
-        });
-
         vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){
             C99Struct& self = _CAST(C99Struct&, lhs);
             if(!is_non_tagged_type(rhs, C99Struct::_type(vm))) return vm->NotImplemented;
@@ -198,8 +186,7 @@ namespace pkpy{
 
         vm->bind_method<1>(type, "read_struct", [](VM* vm, ArgsView args){
             VoidP& self = _CAST(VoidP&, args[0]);
-            const Str& type = CAST(Str&, args[1]);
-            int size = c99_sizeof(vm, type);
+            int size = CAST(int, args[1]);
             return VAR_T(C99Struct, self.ptr, size);
         });
 
@@ -211,30 +198,6 @@ namespace pkpy{
         });
     }
 
-    void C99ReflType::_register(VM* vm, PyObject* mod, PyObject* type){
-        vm->bind_notimplemented_constructor<C99ReflType>(type);
-
-        vm->bind_method<0>(type, "__call__", [](VM* vm, ArgsView args){
-            C99ReflType& self = _CAST(C99ReflType&, args[0]);
-            return VAR_T(C99Struct, nullptr, self.size);
-        });
-
-        vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args){
-            C99ReflType& self = _CAST(C99ReflType&, args[0]);
-            return VAR("<ctype '" + Str(self.name) + "'>");
-        });
-
-        vm->bind_method<0>(type, "name", [](VM* vm, ArgsView args){
-            C99ReflType& self = _CAST(C99ReflType&, args[0]);
-            return VAR(self.name);
-        });
-
-        vm->bind_method<0>(type, "size", [](VM* vm, ArgsView args){
-            C99ReflType& self = _CAST(C99ReflType&, args[0]);
-            return VAR(self.size);
-        });
-    }
-
 void add_module_c(VM* vm){
     PyObject* mod = vm->new_module("c");
     
@@ -267,50 +230,44 @@ void add_module_c(VM* vm){
 
     vm->bind_func<1>(mod, "sizeof", [](VM* vm, ArgsView args){
         const Str& type = CAST(Str&, args[0]);
-        i64 size = c99_sizeof(vm, type);
-        return VAR(size);
-    });
-
-    vm->bind_func<1>(mod, "refl", [](VM* vm, ArgsView args){
-        const Str& key = CAST(Str&, args[0]);
-        auto it = _refl_types.find(key.sv());
-        if(it == _refl_types.end()) vm->ValueError("reflection type not found");
-        const ReflType& rt = it->second;
-        return VAR_T(C99ReflType, rt);
+        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);
-    C99ReflType::register_class(vm, mod);
     mod->attr().set("NULL", VAR_T(VoidP, nullptr));
 
-    add_refl_type("char", sizeof(char));
-    add_refl_type("uchar", sizeof(unsigned char));
-    add_refl_type("short", sizeof(short));
-    add_refl_type("ushort", sizeof(unsigned short));
-    add_refl_type("int", sizeof(int));
-    add_refl_type("uint", sizeof(unsigned int));
-    add_refl_type("long", sizeof(long));
-    add_refl_type("ulong", sizeof(unsigned long));
-    add_refl_type("longlong", sizeof(long long));
-    add_refl_type("ulonglong", sizeof(unsigned long long));
-    add_refl_type("float", sizeof(float));
-    add_refl_type("double", sizeof(double));
-    add_refl_type("bool", sizeof(bool));
     add_refl_type("void_p", sizeof(void*));
-
     PyObject* void_p_t = mod->attr("void_p");
-    for(const char* t: {"char", "uchar", "short", "ushort", "int", "uint", "long", "ulong", "longlong", "ulonglong", "float", "double", "bool"}){
-        mod->attr().set(Str(t) + "_", VAR_T(C99ReflType, _refl_types[t]));
-        mod->attr().set(Str(t) + "_p", void_p_t);
-    }
-}
 
-int c99_sizeof(VM* vm, const Str& type){
-    auto it = _refl_types.find(type.sv());
-    if(it != _refl_types.end()) return it->second.size;
-    vm->ValueError("not a valid c99 type");
-    return 0;
+#define BIND_PRIMITIVE(T, name) \
+    vm->bind_func<1>(mod, name "_", [](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);                           \
+
+    BIND_PRIMITIVE(char, "char")
+    BIND_PRIMITIVE(unsigned char, "uchar")
+    BIND_PRIMITIVE(short, "short")
+    BIND_PRIMITIVE(unsigned short, "ushort")
+    BIND_PRIMITIVE(int, "int")
+    BIND_PRIMITIVE(unsigned int, "uint")
+    BIND_PRIMITIVE(long, "long")
+    BIND_PRIMITIVE(unsigned long, "ulong")
+    BIND_PRIMITIVE(long long, "longlong")
+    BIND_PRIMITIVE(unsigned long long, "ulonglong")
+    BIND_PRIMITIVE(float, "float")
+    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);
 }
 
 }   // namespace pkpy

+ 12 - 0
src/pocketpy.cpp

@@ -352,6 +352,18 @@ void init_builtins(VM* _vm) {
         return vm->heap.gcnew<DummyInstance>(t);
     });
 
+    _vm->bind_method<0>("object", "_enable_instance_dict", [](VM* vm, ArgsView args){
+        PyObject* self = args[0];
+        if(is_tagged(self)){
+            vm->TypeError("object: tagged object cannot enable instance dict");
+        }
+        if(self->is_attr_valid()){
+            vm->TypeError("object: instance dict is already enabled");
+        }
+        self->enable_instance_dict();
+        return vm->None;
+    });
+
     _vm->bind_constructor<2>("type", PK_LAMBDA(vm->_t(args[1])));
 
     _vm->bind_constructor<-1>("range", [](VM* vm, ArgsView args) {

+ 3 - 8
tests/80_c.py

@@ -1,23 +1,18 @@
 import c
 
-c_int = c.refl("int")
-assert c_int.size() == c.sizeof("int")
 array = c.malloc(c.sizeof("int") * 10)
 
 for i in range(10):
     off = c.sizeof("int") * i
     (array+off).write_int(i)
 
-x = c_int()
-x.addr().write_int(0)
+x = c.int_(0)
 for i in range(10):
     off = c.sizeof("int") * i
     i = (array+off).read_int()
-    x.addr().write_int(
-        x.addr().read_int() + i
-    )
+    x.write_int(x.read_int() + i)
 
-assert x.addr().read_int() == (0+9)*10//2
+assert x.read_int() == (0+9)*10//2
 
 c.memset(array, 0, c.sizeof("int") * 10)
 

+ 4 - 1
tests/80_linalg.py

@@ -332,7 +332,10 @@ for i in range(3):
     for j in range(3):
         list_mat[i][j] = test_mat[i, j]
 determinant = list_mat[0][0]*(list_mat[1][1]*list_mat[2][2] - list_mat[1][2]*list_mat[2][1]) - list_mat[0][1]*(list_mat[1][0]*list_mat[2][2] - list_mat[1][2]*list_mat[2][0]) + list_mat[0][2]*(list_mat[1][0]*list_mat[2][1] - list_mat[1][1]*list_mat[2][0])
-assert round(determinant, 3) == round(test_mat_copy.determinant(), 3)
+_0 = determinant
+_1 = test_mat_copy.determinant()
+_0, _1 = round(_0, 2), round(_1, 2)
+assert (_0 == _1), f'{_0} != {_1}'
 
 
 

+ 16 - 20
tests/99_cffi_2.py

@@ -1,14 +1,5 @@
 import c
 
-c_int = c.refl("int")
-assert c_int.name() == "int"
-assert c_int.__repr__() == '<ctype \'int\'>'
-# ------------------------------------------------
-c_int_1 = c.refl("int")
-c_struct_1 = c_int_1()
-assert (c_int_1() == c_int_1())
-assert (c_struct_1 == c_struct_1) == True
-# ------------------------------------------------
 assert c.void_p.from_hex('0x2568b60').hex() == '0x2568b60'
 
 # ------------------------------------------------
@@ -49,17 +40,15 @@ 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.struct(c_void_1, 32)
-
-data_str = "Hello, World!"
-my_struct3 = c.struct(data_str)
+my_struct2 = c_void_1.read_struct(32)
+assert my_struct2.size() == 32
 
 data_bytes = bytes([1,2,3])
 my_struct4 = c.struct(data_bytes)
 
 try:
    c.struct(True)
-   raise Exception('c.struct 的构造方法未能触发 TypeError("expected int, str or bytes")')
+   raise Exception('c.struct 的构造方法未能触发 TypeError("expected int or bytes")')
 except TypeError:
    pass
 
@@ -75,18 +64,25 @@ assert my_struct1.size() == 16
 # 对 c.struct 的 copy 方法的测试不完全
 assert my_struct1.copy().size() == 16
 
-data_str = "Hello, World!"
-my_struct3 = c.struct(data_str)
-assert my_struct3.to_string() == data_str
-
 data_bytes = bytes([1,2,3])
 my_struct4 = c.struct(data_bytes)
-assert my_struct4.to_bytes() == data_bytes
+assert my_struct4.addr().read_bytes(
+    my_struct4.size()
+) == data_bytes
 
 
 # ------------------------------------------------
 # 此处测试并不完全
 c_void_1 = c.malloc(16)
 my_struct1 = c.struct(16)
-c_void_1.read_struct('long')
 c_void_1.write_struct(my_struct1)
+assert c_void_1.read_struct(16) == my_struct1
+
+from c import array, int_
+a = array(10, item_size=4)
+assert a.item_count == 10
+assert a.item_size == 4
+
+_ = hash(a)
+a[4] = int_(123)
+assert a[4] == int_(123)