blueloveTH 2 年之前
父節點
當前提交
ca8fd6b7b1
共有 3 個文件被更改,包括 67 次插入2 次删除
  1. 60 0
      src/cffi.h
  2. 1 1
      src/common.h
  3. 6 1
      src/obj.h

+ 60 - 0
src/cffi.h

@@ -49,6 +49,26 @@ struct VoidP{
     }
 };
 
+struct PlainOldData{
+    PY_CLASS(PlainOldData, c, pod)
+
+    char* p;
+
+    template<typename T>
+    PlainOldData(const T& data){
+        static_assert(std::is_pod_v<T>);
+        p = new char[sizeof(T)];
+        memcpy(p, &data, sizeof(T));
+    }
+
+    PlainOldData(): p(nullptr){}
+    ~PlainOldData(){ delete[] p; }
+
+    static void _register(VM* vm, PyObject* mod, PyObject* type){
+        vm->bind_default_constructor<PlainOldData>(type);
+    }
+};
+
 inline void add_module_c(VM* vm){
     PyObject* mod = vm->new_module("c");
     VoidP::register_class(vm, mod);
@@ -68,4 +88,44 @@ T to_void_p(VM* vm, PyObject* var){
     VoidP& p = CAST(VoidP&, var);
     return reinterpret_cast<T>(p.ptr);
 }
+
+template<typename T>
+T to_plain_old_data(VM* vm, PyObject* var){
+    static_assert(std::is_pod_v<T>);
+    PlainOldData& pod = CAST(PlainOldData&, var);
+    return *reinterpret_cast<T*>(pod.p);
+}
+
+template<typename T>
+std::enable_if_t<std::is_pod_v<T>, PyObject*> py_var(VM* vm, const T& data){
+    return VAR_T(PlainOldData, data);
+}
+/*****************************************************************/
+template<typename Ret, typename... Params>
+struct NativeProxyFuncC {
+    static constexpr int N = sizeof...(Params);
+    using _Fp = Ret(*)(Params...);
+    _Fp func;
+    NativeProxyFuncC(_Fp func) : func(func) {}
+
+    PyObject* operator()(VM* vm, ArgsView args) {
+        if (args.size() != N) {
+            vm->TypeError("expected " + std::to_string(N) + " arguments, but got " + std::to_string(args.size()));
+        }
+        return call<Ret>(vm, args, std::make_index_sequence<N>());
+    }
+
+    template<typename __Ret, size_t... Is>
+    std::enable_if_t<std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
+        func(py_cast<Params>(vm, args[Is])...);
+        return vm->None;
+    }
+
+    template<typename __Ret, size_t... Is>
+    std::enable_if_t<!std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
+        __Ret ret = func(py_cast<Params>(vm, args[Is])...);
+        return VAR(std::move(ret));
+    }
+};
+
 }   // namespace pkpy

+ 1 - 1
src/common.h

@@ -29,7 +29,7 @@
 #include <variant>
 #include <type_traits>
 
-#define PK_VERSION				"0.9.9"
+#define PK_VERSION				"1.0.0"
 
 // debug macros
 #define DEBUG_NO_BUILTIN_MODULES	0

+ 6 - 1
src/obj.h

@@ -224,6 +224,7 @@ template <typename, typename=void> struct is_py_class : std::false_type {};
 template <typename T> struct is_py_class<T, std::void_t<decltype(T::_type)>> : std::true_type {};
 
 template<typename T> T to_void_p(VM*, PyObject*);
+template<typename T> T to_plain_old_data(VM*, PyObject*);
 
 template<typename __T>
 __T py_cast(VM* vm, PyObject* obj) {
@@ -233,6 +234,8 @@ __T py_cast(VM* vm, PyObject* obj) {
     }else if constexpr(is_py_class<T>::value){
         T::_check_type(vm, obj);
         return OBJ_GET(T, obj);
+    }else if constexpr(std::is_pod_v<T>){
+        return to_plain_old_data<T>(vm, obj);
     }else {
         return Discarded();
     }
@@ -245,7 +248,9 @@ __T _py_cast(VM* vm, PyObject* obj) {
         return to_void_p<__T>(vm, obj);
     }else if constexpr(is_py_class<T>::value){
         return OBJ_GET(T, obj);
-    }else{
+    }else if constexpr(std::is_pod_v<T>){
+        return to_plain_old_data<T>(vm, obj);
+    }else {
         return Discarded();
     }
 }