blueloveTH 2 лет назад
Родитель
Сommit
b101049a66
3 измененных файлов с 136 добавлено и 34 удалено
  1. 36 14
      src/c.pyi
  2. 94 18
      src/cffi.h
  3. 6 2
      src/obj.h

+ 36 - 14
src/c.pyi

@@ -3,6 +3,11 @@ 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': ...
+
+class _refl:
+    __name__: str
+    __size__: int
 
 class void_p:
     def __add__(self, i: int) -> 'void_p': ...
@@ -10,20 +15,37 @@ class void_p:
     def __eq__(self, other: 'void_p') -> bool: ...
     def __ne__(self, other: 'void_p') -> bool: ...
 
-    def char(self) -> int: ...
-    def uchar(self) -> int: ...
-    def short(self) -> int: ...
-    def ushort(self) -> int: ...
-    def int(self) -> int: ...
-    def uint(self) -> int: ...
-    def long(self) -> int: ...
-    def ulong(self) -> int: ...
-    def longlong(self) -> int: ...
-    def ulonglong(self) -> int: ...
-    def float(self) -> float: ...
-    def double(self) -> float: ...
-    def bool(self) -> bool: ...
-    def void_p(self) -> 'void_p': ...
+    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 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 get_base_offset(self) -> int: ...
     @overload

+ 94 - 18
src/cffi.h

@@ -113,11 +113,11 @@ struct VoidP{
         });
 
 #define BIND_SETGET(T, name) \
-        vm->bind_method<0>(type, name, [](VM* vm, ArgsView args){   \
+        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, "set_" name, [](VM* vm, ArgsView args){   \
+        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;                                        \
@@ -137,21 +137,36 @@ struct VoidP{
         BIND_SETGET(double, "double")
         BIND_SETGET(bool, "bool")
 
-        vm->bind_method<0>(type, "void_p", [](VM* vm, ArgsView args){
+        vm->bind_method<0>(type, "read_void_p", [](VM* vm, ArgsView args){
             VoidP& self = _CAST(VoidP&, args[0]);
             return VAR_T(VoidP, *(void**)self.ptr);
         });
-        vm->bind_method<1>(type, "set_void_p", [](VM* vm, ArgsView args){
+        vm->bind_method<1>(type, "write_void_p", [](VM* vm, ArgsView args){
             VoidP& self = _CAST(VoidP&, args[0]);
             VoidP& other = CAST(VoidP&, args[0]);
             self.ptr = other.ptr;
             return vm->None;
         });
+
+        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;
+        });
     }
 };
 
-struct Struct{
-    PY_CLASS(Struct, c, struct)
+struct C99Struct{
+    PY_CLASS(C99Struct, c, struct)
 
     static constexpr int INLINE_SIZE = 32;
 
@@ -159,7 +174,7 @@ struct Struct{
     char* p;
 
     template<typename T>
-    Struct(const T& data){
+    C99Struct(const T& data){
         static_assert(std::is_pod_v<T>);
         if(sizeof(T) <= INLINE_SIZE){
             memcpy(_inlined, &data, sizeof(T));
@@ -170,10 +185,10 @@ struct Struct{
         }
     }
 
-    Struct() { p = _inlined; }
-    ~Struct(){ if(p!=_inlined) free(p); }
+    C99Struct() { p = _inlined; }
+    ~C99Struct(){ if(p!=_inlined) free(p); }
 
-    Struct(const Struct& other){
+    C99Struct(const C99Struct& other){
         if(other.p == other._inlined){
             memcpy(_inlined, other._inlined, INLINE_SIZE);
             p = _inlined;
@@ -184,21 +199,68 @@ struct Struct{
     }
 
     static void _register(VM* vm, PyObject* mod, PyObject* type){
-        vm->bind_default_constructor<Struct>(type);
+        vm->bind_default_constructor<C99Struct>(type);
 
         vm->bind_method<0>(type, "address", [](VM* vm, ArgsView args){
-            Struct& self = _CAST(Struct&, args[0]);
+            C99Struct& self = _CAST(C99Struct&, args[0]);
             return VAR_T(VoidP, self.p);
         });
 
         vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){
-            const Struct& self = _CAST(Struct&, args[0]);
-            return VAR_T(Struct, self);
+            const C99Struct& self = _CAST(C99Struct&, args[0]);
+            return VAR_T(C99Struct, self);
+        });
+
+        // patch void_p
+        // type = vm->_t(VoidP::_type(vm));
+
+        // vm->bind_method<1>(type, "read_struct", [](VM* vm, ArgsView args){
+        //     VoidP& self = _CAST(VoidP&, args[0]);
+        //     Str& type = CAST(Str&, args[1]);
+        //     return VAR_T(C99Struct)
+        // });
+
+        // vm->bind_method<1>(type, "write_struct", [](VM* vm, ArgsView args){
+        //     VoidP& self = _CAST(VoidP&, args[0]);
+        //     Str& type = CAST(Str&, args[1]);
+        //     VoidP& other = CAST(VoidP&, args[2]);
+        //     c99_write_struct(vm, type, self.ptr, other.ptr);
+        //     return vm->None;
+        // });
+    }
+};
+
+struct ReflField{
+    std::string_view name;
+    int offset;
+};
+
+struct ReflType{
+    std::string_view name;
+    size_t size;
+    std::vector<ReflField> fields;
+};
+inline static std::map<std::string_view, ReflType> _refl_types;
+
+template<typename T>
+inline void add_refl_type(std::string_view name, std::initializer_list<ReflField> fields){
+    _refl_types[name] = {name, sizeof(T), fields};
+}
+
+struct C99ReflType{
+    PY_CLASS(C99ReflType, c, "_refl")
+    Str repr;
+    static void _register(VM* vm, PyObject* mod, PyObject* type){
+        vm->bind_constructor<-1>(type, CPP_NOT_IMPLEMENTED());
+
+        vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args){
+            C99ReflType& self = _CAST(C99ReflType&, args[0]);
+            return VAR(self.repr);
         });
     }
 };
 
-static_assert(sizeof(Py_<Struct>) <= 64);
+static_assert(sizeof(Py_<C99Struct>) <= 64);
 
 inline PyObject* py_var(VM* vm, void* p){
     return VAR_T(VoidP, p);
@@ -218,13 +280,13 @@ T to_void_p(VM* vm, PyObject* var){
 template<typename T>
 T to_plain_old_data(VM* vm, PyObject* var){
     static_assert(std::is_pod_v<T>);
-    Struct& pod = CAST(Struct&, var);
+    C99Struct& pod = CAST(C99Struct&, var);
     return *reinterpret_cast<T*>(pod.p);
 }
 
 template<typename T>
 std::enable_if_t<std::is_pod_v<T> && !std::is_pointer_v<T>, PyObject*> py_var(VM* vm, const T& data){
-    return VAR_T(Struct, data);
+    return VAR_T(C99Struct, data);
 }
 /*****************************************************************/
 struct NativeProxyFuncCBase {
@@ -297,8 +359,22 @@ inline void add_module_c(VM* vm){
         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;
+        PyObject* obj = VAR_T(C99ReflType);
+        obj->enable_instance_dict();
+        obj->attr().set("__name__", VAR(rt.name));
+        obj->attr().set("__size__", VAR(rt.size));
+        for(auto [k,v]: rt.fields) obj->attr().set(StrName::get(k), VAR(v));
+        return obj;
+    });
+
     VoidP::register_class(vm, mod);
-    Struct::register_class(vm, mod);
+    C99Struct::register_class(vm, mod);
+    C99ReflType::register_class(vm, mod);
     mod->attr().set("NULL", VAR_T(VoidP, nullptr));
 }
 

+ 6 - 2
src/obj.h

@@ -229,7 +229,9 @@ template<typename T> T to_plain_old_data(VM*, PyObject*);
 template<typename __T>
 __T py_cast(VM* vm, PyObject* obj) {
     using T = std::decay_t<__T>;
-    if constexpr(std::is_pointer_v<T>){
+    if constexpr(std::is_enum_v<T>){
+        return (__T)py_cast<i64>(vm, obj);
+    }else if constexpr(std::is_pointer_v<T>){
         return to_void_p<T>(vm, obj);
     }else if constexpr(is_py_class<T>::value){
         T::_check_type(vm, obj);
@@ -244,7 +246,9 @@ __T py_cast(VM* vm, PyObject* obj) {
 template<typename __T>
 __T _py_cast(VM* vm, PyObject* obj) {
     using T = std::decay_t<__T>;
-    if constexpr(std::is_pointer_v<__T>){
+    if constexpr(std::is_enum_v<T>){
+        return (__T)_py_cast<i64>(vm, obj);
+    }else if constexpr(std::is_pointer_v<__T>){
         return to_void_p<__T>(vm, obj);
     }else if constexpr(is_py_class<T>::value){
         return OBJ_GET(T, obj);