blueloveTH 2 سال پیش
والد
کامیت
778a70e90f
8فایلهای تغییر یافته به همراه54 افزوده شده و 6 حذف شده
  1. 14 0
      include/pocketpy/bindings.h
  2. 1 1
      include/pocketpy/linalg.h
  3. 3 0
      include/pocketpy/str.h
  4. 7 3
      include/pocketpy/vm.h
  5. 3 0
      include/typings/c.pyi
  6. 11 1
      src/cffi.cpp
  7. 8 0
      src/linalg.cpp
  8. 7 1
      tests/80_linalg.py

+ 14 - 0
include/pocketpy/bindings.h

@@ -113,4 +113,18 @@ void _bind(VM* vm, PyObject* obj, const char* sig, Ret(T::*func)(Params...)){
                 return VAR(self.REF().FGET());          \
             });
 
+#define PY_STRUCT_LIKE_OBJECT(T)   \
+        static_assert(std::is_trivially_copyable<T>::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>(T::_type(vm));    \
+            memcpy(&_CAST(T&, obj), s.p, sizeof(T));            \
+            return obj;                                         \
+        });                                                     \
+        vm->bind_method<0>(type, "__to_struct__", [](VM* vm, ArgsView args){    \
+            T& self = _CAST(T&, args[0]);                       \
+            return VAR_T(C99Struct, &self, sizeof(T));          \
+        });
+
 }   // namespace pkpy

+ 1 - 1
include/pocketpy/linalg.h

@@ -1,6 +1,6 @@
 #pragma once
 
-#include "cffi.h"
+#include "bindings.h"
 
 namespace pkpy{
 

+ 3 - 0
include/pocketpy/str.h

@@ -192,6 +192,9 @@ 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");

+ 7 - 3
include/pocketpy/vm.h

@@ -399,10 +399,14 @@ public:
         return _all_types[t.index].obj;
     }
 
+    Type _tp(PyObject* obj){
+        if(is_int(obj)) return tp_int;
+        if(is_float(obj)) return tp_float;
+        return obj->type;
+    }
+
     PyObject* _t(PyObject* obj){
-        if(is_int(obj)) return _t(tp_int);
-        if(is_float(obj)) return _t(tp_float);
-        return _all_types[obj->type].obj;
+        return _all_types[_tp(obj).index].obj;
     }
 
     struct ImportContext{

+ 3 - 0
include/typings/c.pyi

@@ -127,3 +127,6 @@ class array(struct):
     def __getitem__(self, index: int) -> 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): ...

+ 11 - 1
src/cffi.cpp

@@ -1,4 +1,5 @@
 #include "pocketpy/cffi.h"
+#include "pocketpy/str.h"
 
 namespace pkpy{
 
@@ -136,7 +137,7 @@ namespace pkpy{
 
         vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){
             const C99Struct& self = _CAST(C99Struct&, args[0]);
-            return VAR_T(C99Struct, self);
+            return vm->heap.gcnew<C99Struct>(vm->_tp(args[0]), self);
         });
 
         vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){
@@ -233,6 +234,15 @@ 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));

+ 8 - 0
src/linalg.cpp

@@ -48,6 +48,8 @@ namespace pkpy{
 
 
     void PyVec2::_register(VM* vm, PyObject* mod, PyObject* type){
+        PY_STRUCT_LIKE_OBJECT(PyVec2)
+
         vm->bind_constructor<3>(type, [](VM* vm, ArgsView args){
             float x = CAST_F(args[1]);
             float y = CAST_F(args[2]);
@@ -112,6 +114,8 @@ namespace pkpy{
     }
 
     void PyVec3::_register(VM* vm, PyObject* mod, PyObject* type){
+        PY_STRUCT_LIKE_OBJECT(PyVec3)
+
         vm->bind_constructor<4>(type, [](VM* vm, ArgsView args){
             float x = CAST_F(args[1]);
             float y = CAST_F(args[2]);
@@ -154,6 +158,8 @@ namespace pkpy{
     }
 
     void PyVec4::_register(VM* vm, PyObject* mod, PyObject* type){
+        PY_STRUCT_LIKE_OBJECT(PyVec4)
+
         vm->bind_constructor<1+4>(type, [](VM* vm, ArgsView args){
             float x = CAST_F(args[1]);
             float y = CAST_F(args[2]);
@@ -204,6 +210,8 @@ namespace pkpy{
 #undef BIND_VEC_FUNCTION_1
 
     void PyMat3x3::_register(VM* vm, PyObject* mod, PyObject* type){
+        PY_STRUCT_LIKE_OBJECT(PyMat3x3)
+
         vm->bind_constructor<-1>(type, [](VM* vm, ArgsView args){
             if(args.size() == 1+0) return VAR_T(PyMat3x3, Mat3x3::zeros());
             if(args.size() == 1+9){

+ 7 - 1
tests/80_linalg.py

@@ -470,4 +470,10 @@ temp_vec2 = test_mat_copy.transform_point(test_vec2_copy)
 test_mat_copy = test_mat.copy()
 test_mat_copy = test_mat.copy()
 test_vec2_copy = test_vec2.copy()
-temp_vec2 = test_mat_copy.transform_vector(test_vec2_copy)
+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