diff --git a/3rd/lua_bridge/src/lua_bridge.cpp b/3rd/lua_bridge/src/lua_bridge.cpp index 70da825e..e7ee296d 100644 --- a/3rd/lua_bridge/src/lua_bridge.cpp +++ b/3rd/lua_bridge/src/lua_bridge.cpp @@ -198,7 +198,7 @@ static PyObject* lua_popx_multi_to_python(VM* vm, int count){ struct PyLuaFunction: PyLuaObject{ static void _register(VM* vm, PyObject* mod, PyObject* type){ vm->bind_notimplemented_constructor(type); - vm->bind_method<-1>(type, __call__, [](VM* vm, ArgsView args){ + vm->bind_func(type, __call__, -1, [](VM* vm, ArgsView args){ if(args.size() < 1) vm->TypeError("__call__ takes at least 1 argument"); const PyLuaFunction& self = _CAST(PyLuaFunction&, args[0]); int base_size = lua_gettop(_L); diff --git a/include/pocketpy/bindings.h b/include/pocketpy/bindings.h index 33c6358f..84bae6d1 100644 --- a/include/pocketpy/bindings.h +++ b/include/pocketpy/bindings.h @@ -163,19 +163,19 @@ void _bind(VM* vm, PyObject* obj, const char* sig, Ret(T::*func)(Params...)){ memcpy(&_CAST(wT&, obj), s.p, sizeof(wT)); \ return obj; \ }, {}, BindType::STATICMETHOD); \ - vm->bind_method<0>(type, "tostruct", [](VM* vm, ArgsView args){ \ + vm->bind_func(type, "tostruct", 1, [](VM* vm, ArgsView args){ \ wT& self = _CAST(wT&, args[0]); \ return vm->new_user_object(&self, sizeof(wT)); \ }); \ - vm->bind_method<0>(type, "addr", [](VM* vm, ArgsView args){ \ + vm->bind_func(type, "addr", 1, [](VM* vm, ArgsView args){ \ wT& self = _CAST(wT&, args[0]); \ return vm->new_user_object(&self); \ }); \ - vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){ \ + vm->bind_func(type, "copy", 1, [](VM* vm, ArgsView args){ \ wT& self = _CAST(wT&, args[0]); \ return vm->new_user_object(self); \ }); \ - vm->bind_method<0>(type, "sizeof", [](VM* vm, ArgsView args){ \ + vm->bind_func(type, "sizeof", 1, [](VM* vm, ArgsView args){ \ return VAR(sizeof(wT)); \ }); \ vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ \ diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index 36e90a29..7d435c3b 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -296,13 +296,14 @@ public: void bind__setitem__(Type type, void (*f)(VM*, PyObject*, PyObject*, PyObject*)); void bind__delitem__(Type type, void (*f)(VM*, PyObject*, PyObject*)); - template - PyObject* bind_method(Type, StrName, NativeFuncC); - template - PyObject* bind_method(PyObject*, StrName, NativeFuncC); template PyObject* bind_func(PyObject*, StrName, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT); + // new style binding api + PyObject* bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, UserData userdata={}, BindType bt=BindType::DEFAULT); + PyObject* bind_func(Type type, StrName name, int argc, NativeFuncC fn, UserData userdata={}, BindType bt=BindType::DEFAULT){ + return bind_func(_t(type), name, argc, fn, userdata, bt); + } PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT); PyObject* bind(PyObject*, const char*, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT); PyObject* bind_property(PyObject*, const char*, NativeFuncC fget, NativeFuncC fset=nullptr); @@ -555,20 +556,6 @@ __T py_cast(VM* vm, PyObject* obj) { return _py_cast__internal<__T, true>(vm, o template __T _py_cast(VM* vm, PyObject* obj) { return _py_cast__internal<__T, false>(vm, obj); } - -template -PyObject* VM::bind_method(Type type, StrName name, NativeFuncC fn) { - PyObject* nf = VAR(NativeFunc(fn, ARGC, true)); - _t(type)->attr().set(name, nf); - return nf; -} - -template -PyObject* VM::bind_method(PyObject* obj, StrName name, NativeFuncC fn) { - check_type(obj, tp_type); - return bind_method(PK_OBJ_GET(Type, obj), name, fn); -} - template PyObject* VM::bind_func(PyObject* obj, StrName name, NativeFuncC fn, UserData userdata, BindType bt) { PyObject* nf = VAR(NativeFunc(fn, ARGC, false)); diff --git a/src/cffi.cpp b/src/cffi.cpp index 63641a4e..8730aea0 100644 --- a/src/cffi.cpp +++ b/src/cffi.cpp @@ -44,7 +44,7 @@ namespace pkpy{ return vm->heap.gcnew(cls, size); }); - vm->bind_method<0>(type, "hex", [](VM* vm, ArgsView args){ + vm->bind_func(type, "hex", 1, [](VM* vm, ArgsView args){ const Struct& self = _CAST(Struct&, args[0]); SStream ss; for(int i=0; ibind_method<0>(type, "addr", [](VM* vm, ArgsView args){ + vm->bind_func(type, "addr", 1, [](VM* vm, ArgsView args){ Struct& self = _CAST(Struct&, args[0]); return vm->new_user_object(self.p); }); - vm->bind_method<0>(type, "sizeof", [](VM* vm, ArgsView args){ + vm->bind_func(type, "sizeof", 1, [](VM* vm, ArgsView args){ Struct& self = _CAST(Struct&, args[0]); return VAR(self.size); }); - vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){ + vm->bind_func(type, "copy", 1, [](VM* vm, ArgsView args){ const Struct& self = _CAST(Struct&, args[0]); return vm->heap.gcnew(vm->_tp(args[0]), self); }); @@ -198,12 +198,12 @@ void add_module_c(VM* vm){ type = vm->new_type_object(mod, CNAME "_p", vm->_tp_user()); \ mod->attr().set(CNAME "_p", type); \ type_t = PK_OBJ_GET(Type, type); \ - vm->bind_method<0>(type, "read", [](VM* vm, ArgsView args){ \ + vm->bind_func(type, "read", 1, [](VM* vm, ArgsView args){ \ VoidP& voidp = PK_OBJ_GET(VoidP, args[0]); \ T* target = (T*)voidp.ptr; \ return VAR(*target); \ }); \ - vm->bind_method<1>(type, "write", [](VM* vm, ArgsView args){ \ + vm->bind_func(type, "write", 2, [](VM* vm, ArgsView args){ \ VoidP& voidp = PK_OBJ_GET(VoidP, args[0]); \ T val = CAST(T, args[1]); \ T* target = (T*)voidp.ptr; \ diff --git a/src/io.cpp b/src/io.cpp index 76d2061c..e6d7ff76 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -83,7 +83,7 @@ void FileIO::_register(VM* vm, PyObject* mod, PyObject* type){ return VAR(std::move(b)); }); - vm->bind_method<1>(type, "write", [](VM* vm, ArgsView args){ + vm->bind_func(type, "write", 2, [](VM* vm, ArgsView args){ FileIO& io = PK_OBJ_GET(FileIO, args[0]); if(io.is_text){ Str& s = CAST(Str&, args[1]); @@ -95,14 +95,14 @@ void FileIO::_register(VM* vm, PyObject* mod, PyObject* type){ return vm->None; }); - vm->bind_method<0>(type, "tell", [](VM* vm, ArgsView args){ + vm->bind_func(type, "tell", 1, [](VM* vm, ArgsView args){ FileIO& io = PK_OBJ_GET(FileIO, args[0]); long pos = ftell(io.fp); if(pos == -1) vm->IOError(strerror(errno)); return VAR(pos); }); - vm->bind_method<2>(type, "seek", [](VM* vm, ArgsView args){ + vm->bind_func(type, "seek", 3, [](VM* vm, ArgsView args){ FileIO& io = PK_OBJ_GET(FileIO, args[0]); long offset = CAST(long, args[1]); int whence = CAST(int, args[2]); @@ -111,19 +111,19 @@ void FileIO::_register(VM* vm, PyObject* mod, PyObject* type){ return vm->None; }); - vm->bind_method<0>(type, "close", [](VM* vm, ArgsView args){ + vm->bind_func(type, "close", 1, [](VM* vm, ArgsView args){ FileIO& io = PK_OBJ_GET(FileIO, args[0]); io.close(); return vm->None; }); - vm->bind_method<0>(type, "__exit__", [](VM* vm, ArgsView args){ + vm->bind_func(type, __exit__, 1, [](VM* vm, ArgsView args){ FileIO& io = PK_OBJ_GET(FileIO, args[0]); io.close(); return vm->None; }); - vm->bind_method<0>(type, "__enter__", PK_LAMBDA(args[0])); + vm->bind_func(type, __enter__, 1, PK_LAMBDA(args[0])); } FileIO::FileIO(VM* vm, const Str& file, const Str& mode){ diff --git a/src/linalg.cpp b/src/linalg.cpp index fd10127c..09aae4a5 100644 --- a/src/linalg.cpp +++ b/src/linalg.cpp @@ -17,13 +17,13 @@ namespace pkpy{ }); #define BIND_VEC_FUNCTION_0(D, name) \ - vm->bind_method<0>(type, #name, [](VM* vm, ArgsView args){ \ + vm->bind_func(type, #name, 1, [](VM* vm, ArgsView args){ \ Vec##D& self = _CAST(Vec##D&, args[0]); \ return VAR(self.name()); \ }); #define BIND_VEC_FUNCTION_1(D, name) \ - vm->bind_method<1>(type, #name, [](VM* vm, ArgsView args){ \ + vm->bind_func(type, #name, 2, [](VM* vm, ArgsView args){ \ Vec##D& self = _CAST(Vec##D&, args[0]); \ Vec##D& other = CAST(Vec##D&, args[1]); \ return VAR(self.name(other)); \ @@ -39,7 +39,7 @@ namespace pkpy{ f64 other = CAST(f64, _1); \ return VAR(self * other); \ }); \ - vm->bind_method<1>(type, "__rmul__", [](VM* vm, ArgsView args){ \ + vm->bind_func(type, "__rmul__", 2, [](VM* vm, ArgsView args){ \ Vec##D& self = _CAST(Vec##D&, args[0]); \ f64 other = CAST(f64, args[1]); \ return VAR(self * other); \ @@ -154,13 +154,13 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s return VAR(ss.str()); }); - vm->bind_method<1>(type, "rotate", [](VM* vm, ArgsView args){ + vm->bind_func(type, "rotate", 2, [](VM* vm, ArgsView args){ Vec2 self = _CAST(Vec2&, args[0]); float radian = CAST(f64, args[1]); return vm->new_user_object(self.rotate(radian)); }); - vm->bind_method<1>(type, "rotate_", [](VM* vm, ArgsView args){ + vm->bind_func(type, "rotate_", 2, [](VM* vm, ArgsView args){ Vec2& self = _CAST(Vec2&, args[0]); float radian = CAST(f64, args[1]); self = self.rotate(radian); @@ -282,7 +282,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s return vm->None; }); - vm->bind_method<1>(type, "copy_", [](VM* vm, ArgsView args){ + vm->bind_func(type, "copy_", 2, [](VM* vm, ArgsView args){ Mat3x3& self = _CAST(Mat3x3&, args[0]); const Mat3x3& other = CAST(Mat3x3&, args[1]); self = other; @@ -355,7 +355,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s return vm->new_user_object(self * other); }); - vm->bind_method<1>(type, "__rmul__", [](VM* vm, ArgsView args){ + vm->bind_func(type, "__rmul__", 2, [](VM* vm, ArgsView args){ Mat3x3& self = _CAST(Mat3x3&, args[0]); f64 other = CAST_F(args[1]); return vm->new_user_object(self * other); @@ -392,12 +392,12 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s } }); - vm->bind_method<0>(type, "determinant", [](VM* vm, ArgsView args){ + vm->bind_func(type, "determinant", 1, [](VM* vm, ArgsView args){ Mat3x3& self = _CAST(Mat3x3&, args[0]); return VAR(self.determinant()); }); - vm->bind_method<0>(type, "transpose", [](VM* vm, ArgsView args){ + vm->bind_func(type, "transpose", 1, [](VM* vm, ArgsView args){ Mat3x3& self = _CAST(Mat3x3&, args[0]); return vm->new_user_object(self.transpose()); }); @@ -409,14 +409,14 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s return vm->new_user_object(ret); }); - vm->bind_method<0>(type, "inverse", [](VM* vm, ArgsView args){ + vm->bind_func(type, "inverse", 1, [](VM* vm, ArgsView args){ Mat3x3& self = _CAST(Mat3x3&, args[0]); Mat3x3 ret; if(!self.inverse(ret)) vm->ValueError("matrix is not invertible"); return vm->new_user_object(ret); }); - vm->bind_method<0>(type, "inverse_", [](VM* vm, ArgsView args){ + vm->bind_func(type, "inverse_", 1, [](VM* vm, ArgsView args){ Mat3x3& self = _CAST(Mat3x3&, args[0]); Mat3x3 ret; if(!self.inverse(ret)) vm->ValueError("matrix is not invertible"); @@ -424,7 +424,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s return vm->None; }); - vm->bind_method<0>(type, "transpose_", [](VM* vm, ArgsView args){ + vm->bind_func(type, "transpose_", 1, [](VM* vm, ArgsView args){ Mat3x3& self = _CAST(Mat3x3&, args[0]); self = self.transpose(); return vm->None; @@ -484,34 +484,34 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s return vm->None; }); - vm->bind_method<0>(type, "is_affine", [](VM* vm, ArgsView args){ + vm->bind_func(type, "is_affine", 1, [](VM* vm, ArgsView args){ Mat3x3& self = _CAST(Mat3x3&, args[0]); return VAR(self.is_affine()); }); - vm->bind_method<0>(type, "_t", [](VM* vm, ArgsView args){ + vm->bind_func(type, "_t", 1, [](VM* vm, ArgsView args){ Mat3x3& self = _CAST(Mat3x3&, args[0]); return vm->new_user_object(self._t()); }); - vm->bind_method<0>(type, "_r", [](VM* vm, ArgsView args){ + vm->bind_func(type, "_r", 1, [](VM* vm, ArgsView args){ Mat3x3& self = _CAST(Mat3x3&, args[0]); return VAR(self._r()); }); - vm->bind_method<0>(type, "_s", [](VM* vm, ArgsView args){ + vm->bind_func(type, "_s", 1, [](VM* vm, ArgsView args){ Mat3x3& self = _CAST(Mat3x3&, args[0]); return vm->new_user_object(self._s()); }); - vm->bind_method<1>(type, "transform_point", [](VM* vm, ArgsView args){ + vm->bind_func(type, "transform_point", 2, [](VM* vm, ArgsView args){ const Mat3x3& self = _CAST(Mat3x3&, args[0]); Vec2 v = CAST(Vec2, args[1]); Vec2 res(self._11 * v.x + self._12 * v.y + self._13, self._21 * v.x + self._22 * v.y + self._23); return vm->new_user_object(res); }); - vm->bind_method<1>(type, "inverse_transform_point", [](VM* vm, ArgsView args){ + vm->bind_func(type, "inverse_transform_point", 2, [](VM* vm, ArgsView args){ const Mat3x3& self = _CAST(Mat3x3&, args[0]); Vec2 v = CAST(Vec2, args[1]); Mat3x3 inv; @@ -520,14 +520,14 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s return vm->new_user_object(res); }); - vm->bind_method<1>(type, "transform_vector", [](VM* vm, ArgsView args){ + vm->bind_func(type, "transform_vector", 2, [](VM* vm, ArgsView args){ const Mat3x3& self = _CAST(Mat3x3&, args[0]); Vec2 v = CAST(Vec2, args[1]); Vec2 res(self._11 * v.x + self._12 * v.y, self._21 * v.x + self._22 * v.y); return vm->new_user_object(res); }); - vm->bind_method<1>(type, "inverse_transform_vector", [](VM* vm, ArgsView args){ + vm->bind_func(type, "inverse_transform_vector", 2, [](VM* vm, ArgsView args){ const Mat3x3& self = _CAST(Mat3x3&, args[0]); Vec2 v = CAST(Vec2, args[1]); Mat3x3 inv; diff --git a/src/random.cpp b/src/random.cpp index c051849c..d8f8a7f1 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -139,13 +139,13 @@ struct Random{ return vm->heap.gcnew(cls); }); - vm->bind_method<1>(type, "seed", [](VM* vm, ArgsView args) { + vm->bind_func(type, "seed", 2, [](VM* vm, ArgsView args) { Random& self = PK_OBJ_GET(Random, args[0]); self.gen.seed(CAST(i64, args[1])); return vm->None; }); - vm->bind_method<2>(type, "randint", [](VM* vm, ArgsView args) { + vm->bind_func(type, "randint", 3, [](VM* vm, ArgsView args) { Random& self = PK_OBJ_GET(Random, args[0]); i64 a = CAST(i64, args[1]); i64 b = CAST(i64, args[2]); @@ -153,12 +153,12 @@ struct Random{ return VAR(self.gen.randint(a, b)); }); - vm->bind_method<0>(type, "random", [](VM* vm, ArgsView args) { + vm->bind_func(type, "random", 1, [](VM* vm, ArgsView args) { Random& self = PK_OBJ_GET(Random, args[0]); return VAR(self.gen.random()); }); - vm->bind_method<2>(type, "uniform", [](VM* vm, ArgsView args) { + vm->bind_func(type, "uniform", 3, [](VM* vm, ArgsView args) { Random& self = PK_OBJ_GET(Random, args[0]); f64 a = CAST(f64, args[1]); f64 b = CAST(f64, args[2]); @@ -166,7 +166,7 @@ struct Random{ return VAR(self.gen.uniform(a, b)); }); - vm->bind_method<1>(type, "shuffle", [](VM* vm, ArgsView args) { + vm->bind_func(type, "shuffle", 2, [](VM* vm, ArgsView args) { Random& self = PK_OBJ_GET(Random, args[0]); List& L = CAST(List&, args[1]); for(int i = L.size() - 1; i > 0; i--){ @@ -176,7 +176,7 @@ struct Random{ return vm->None; }); - vm->bind_method<1>(type, "choice", [](VM* vm, ArgsView args) { + vm->bind_func(type, "choice", 2, [](VM* vm, ArgsView args) { Random& self = PK_OBJ_GET(Random, args[0]); ArgsView view = vm->cast_array_view(args[1]); if(view.empty()) vm->IndexError("cannot choose from an empty sequence"); diff --git a/src/vm.cpp b/src/vm.cpp index 35c37436..c94ea579 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -1222,6 +1222,18 @@ void VM::setattr(PyObject* obj, StrName name, PyObject* value){ obj->attr().set(name, value); } +PyObject* VM::bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, UserData userdata, BindType bt) { + PyObject* nf = VAR(NativeFunc(fn, argc, false)); + PK_OBJ_GET(NativeFunc, nf).set_userdata(userdata); + switch(bt){ + case BindType::DEFAULT: break; + case BindType::STATICMETHOD: nf = VAR(StaticMethod(nf)); break; + case BindType::CLASSMETHOD: nf = VAR(ClassMethod(nf)); break; + } + obj->attr().set(name, nf); + return nf; +} + PyObject* VM::bind(PyObject* obj, const char* sig, NativeFuncC fn, UserData userdata, BindType bt){ return bind(obj, sig, nullptr, fn, userdata, bt); }