diff --git a/imperative/python/src/numpy_dtypes.cpp b/imperative/python/src/numpy_dtypes.cpp index 89310aea..1c195a87 100644 --- a/imperative/python/src/numpy_dtypes.cpp +++ b/imperative/python/src/numpy_dtypes.cpp @@ -117,6 +117,12 @@ struct _wrap { } }(); + static PyObject* impl_py35(PyObject* self, PyObject* args) { + auto* arr = &PyTuple_GET_ITEM(args, 0); + auto size = PyTuple_GET_SIZE(args); + return impl(self, arr, size); + } + static PyObject* impl(PyObject* self, PyObject*const* args, size_t nargs) { if (nargs != n_args) { PyErr_Format(PyExc_ValueError, "expected %lu arguments", n_args); @@ -159,14 +165,21 @@ struct _wrap { } // anonymous namespace +#ifdef METH_FASTCALL +#define MGE_PY_INTERFACE(NAME, FUN) \ + { #NAME, (PyCFunction)_wrap < &(FUN) > ::impl, METH_FASTCALL, nullptr } +#else +#define MGE_PY_INTERFACE(NAME, FUN) \ + { #NAME, (PyCFunction)_wrap < &(FUN) > ::impl_py35, METH_VARARGS, nullptr } +#endif + void init_dtypes(py::module m) { static PyMethodDef method_defs[] = { - {"is_quantize", (PyCFunction)_wrap<&_is_quantize>::impl, METH_FASTCALL, nullptr}, - {"get_scale", (PyCFunction)_wrap<&_get_scale>::impl, METH_FASTCALL, nullptr}, - {"get_zero_point", (PyCFunction)_wrap<&_get_zero_point>::impl, METH_FASTCALL, nullptr}, - {"is_dtype_equal", (PyCFunction)_wrap<&_is_dtype_equal>::impl, METH_FASTCALL, nullptr}, - {nullptr, nullptr, 0, nullptr} - }; + MGE_PY_INTERFACE(is_quantize, _is_quantize), + MGE_PY_INTERFACE(get_scale, _get_scale), + MGE_PY_INTERFACE(get_zero_point, _get_zero_point), + MGE_PY_INTERFACE(is_dtype_equal, _is_dtype_equal), + {nullptr, nullptr, 0, nullptr}}; for (auto&& def: method_defs) { if (def.ml_meth != nullptr) { auto* func = PyCFunction_NewEx(&def, nullptr, nullptr); @@ -176,4 +189,6 @@ void init_dtypes(py::module m) { } } +#undef MGE_PY_INTERFACE + } // namespace mgb diff --git a/imperative/python/src/tensor.cpp b/imperative/python/src/tensor.cpp index f924ddd9..3d5ae0bb 100644 --- a/imperative/python/src/tensor.cpp +++ b/imperative/python/src/tensor.cpp @@ -404,8 +404,6 @@ void TensorWrapper::setscalar() { } -PyMethodDef apply_def{"apply", (PyCFunction)py_apply, METH_FASTCALL, nullptr}; - struct TensorWeakRef { std::weak_ptr wptr; @@ -612,6 +610,24 @@ PyObject* get_device(PyObject* self, PyObject*const* args, size_t nargs) { } } +#ifdef METH_FASTCALL +#define MGE_PY_INTERFACE(NAME, FUNC) \ + { #NAME, (PyCFunction)FUNC, METH_FASTCALL, nullptr } +#else +#define WRAP_FUNC_PY35(FUNC) \ + PyObject* py35_##FUNC(PyObject* self, PyObject* args) { \ + auto* arr = &PyTuple_GET_ITEM(args, 0); \ + auto size = PyTuple_GET_SIZE(args); \ + return FUNC(self, arr, size); \ + } +WRAP_FUNC_PY35(py_apply); +WRAP_FUNC_PY35(dtype_promotion); +WRAP_FUNC_PY35(get_device); +#undef WRAP_FUNC_PY35 +#define MGE_PY_INTERFACE(NAME, FUNC) \ + { #NAME, (PyCFunction)py35_##FUNC, METH_VARARGS, nullptr } +#endif + void init_tensor(py::module m) { interpreter_for_py = interpreter::Interpreter::inst().create_channel(); @@ -643,11 +659,10 @@ void init_tensor(py::module m) { .def("__call__", &TensorWeakRef::operator()); static PyMethodDef method_defs[] = { - {"apply", (PyCFunction)py_apply, METH_FASTCALL, nullptr}, - {"dtype_promotion", (PyCFunction)dtype_promotion, METH_FASTCALL, nullptr}, - {"get_device", (PyCFunction)get_device, METH_FASTCALL, nullptr}, - {nullptr, nullptr, 0, nullptr} - }; + MGE_PY_INTERFACE(apply, py_apply), + MGE_PY_INTERFACE(dtype_promotion, dtype_promotion), + MGE_PY_INTERFACE(get_device, get_device), + {nullptr, nullptr, 0, nullptr}}; for (auto&& def: method_defs) { if (def.ml_meth != nullptr) { auto* func = PyCFunction_NewEx(&def, nullptr, nullptr); @@ -698,4 +713,6 @@ void init_tensor(py::module m) { } +#undef MGE_PY_INTERFACE + } // namespace mgb::imperative::python