#pragma once #include "common.h" #include "vm.h" namespace pkpy { template struct NativeProxyFunc { static constexpr int N = sizeof...(Params); using _Fp = Ret(*)(Params...); _Fp func; NativeProxyFunc(_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(vm, args, std::make_index_sequence()); } template std::enable_if_t, PyObject*> call(VM* vm, ArgsView args, std::index_sequence) { func(py_cast(vm, args[Is])...); return vm->None; } template std::enable_if_t, PyObject*> call(VM* vm, ArgsView args, std::index_sequence) { __Ret ret = func(py_cast(vm, args[Is])...); return VAR(std::move(ret)); } }; template struct NativeProxyMethod { static constexpr int N = sizeof...(Params); using _Fp = Ret(T::*)(Params...); _Fp func; NativeProxyMethod(_Fp func) : func(func) {} PyObject* operator()(VM* vm, ArgsView args) { int actual_size = args.size() - 1; if (actual_size != N) { vm->TypeError("expected " + std::to_string(N) + " arguments, but got " + std::to_string(actual_size)); } return call(vm, args, std::make_index_sequence()); } template std::enable_if_t, PyObject*> call(VM* vm, ArgsView args, std::index_sequence) { T& self = py_cast(vm, args[0]); (self.*func)(py_cast(vm, args[Is+1])...); return vm->None; } template std::enable_if_t, PyObject*> call(VM* vm, ArgsView args, std::index_sequence) { T& self = py_cast(vm, args[0]); __Ret ret = (self.*func)(py_cast(vm, args[Is+1])...); return VAR(std::move(ret)); } }; template auto native_proxy_callable(Ret(*func)(Params...)) { return NativeProxyFunc(func); } template auto native_proxy_callable(Ret(T::*func)(Params...)) { return NativeProxyMethod(func); } struct VoidP{ PY_CLASS(VoidP, c, void_p) void* ptr; VoidP(void* ptr): ptr(ptr){} static void _register(VM* vm, PyObject* mod, PyObject* type){ vm->bind_static_method<1>(type, "__new__", CPP_NOT_IMPLEMENTED()); vm->bind_static_method<1>(type, "__repr__", [](VM* vm, const Args& args){ VoidP& self = CAST(VoidP&, args[0]); std::stringstream ss; ss << ""; return VAR(ss.str()); }); } }; inline void add_module_c(VM* vm){ PyObject* mod = vm->new_module("c"); VoidP::register_class(vm, mod); } inline PyObject* py_var(VM* vm, void* p){ return VAR_T(VoidP, p); } inline PyObject* py_var(VM* vm, char* p){ return VAR_T(VoidP, p); } /***********************************************/ template struct _pointer { static constexpr int level = 0; using baseT = T; }; template struct _pointer { static constexpr int level = _pointer::level + 1; using baseT = typename _pointer::baseT; }; template struct pointer { static constexpr int level = _pointer>::level; using baseT = typename _pointer>::baseT; }; template T py_pointer_cast(VM* vm, PyObject* var){ static_assert(std::is_pointer_v); VoidP& p = CAST(VoidP&, var); return reinterpret_cast(p.ptr); } } // namespace pkpy