diff --git a/CMakeLists.txt b/CMakeLists.txt index 50403dc..ba4098f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,7 +139,7 @@ target_include_directories(cppjit PRIVATE ) target_compile_options(cppjit PRIVATE - -Wall -Wno-strict-aliasing -Wno-register + -Wall -Wextra -Wno-strict-aliasing -Wno-register -Werror ) if(CMAKE_COMPILER_IS_GNUCXX) diff --git a/src/cpyrt/CPPEnum.cxx b/src/cpyrt/CPPEnum.cxx index 6585265..f64dad8 100644 --- a/src/cpyrt/CPPEnum.cxx +++ b/src/cpyrt/CPPEnum.cxx @@ -139,7 +139,7 @@ static PyTypeObject* GetCTypesType(const std::string& cppname) { return (PyTypeObject*)PyObject_GetAttrString(ctmod, nn->second.c_str()); } -static PyObject* enum_ctype(PyObject* cls, PyObject* args, PyObject* kwds) { +static PyObject* enum_ctype(PyObject* cls, PyObject* args) { PyObject* pyres = PyObject_GetAttr(cls, cpyrt::PyStrings::gUnderlying); if (!pyres) PyErr_Clear(); @@ -149,7 +149,7 @@ static PyObject* enum_ctype(PyObject* cls, PyObject* args, PyObject* kwds) { if (!ct) return nullptr; - return PyType_Type.tp_call((PyObject*)ct, args, kwds); + return PyType_Type.tp_call((PyObject*)ct, args, nullptr); } //- creation ----------------------------------------------------------------- @@ -213,7 +213,7 @@ cpyrt::CPPEnum* cpyrt::CPPEnum_New(const std::string& name, // add pythonizations Utility::AddToClass((PyObject*)Py_TYPE(pyenum), "__ctype__", - (PyCFunction)enum_ctype, METH_VARARGS | METH_KEYWORDS); + enum_ctype, METH_VARARGS); ((PyTypeObject*)pyenum)->tp_repr = enum_repr; ((PyTypeObject*)pyenum)->tp_str = ((PyTypeObject*)pyside_type)->tp_repr; diff --git a/src/cpyrt/CPPInstance.cxx b/src/cpyrt/CPPInstance.cxx index 59cde8a..9d9c9d7 100644 --- a/src/cpyrt/CPPInstance.cxx +++ b/src/cpyrt/CPPInstance.cxx @@ -270,18 +270,17 @@ static int op_nonzero(CPPInstance* self) { } //= cpyrt object explicit destruction ===================================== -static PyObject* op_destruct(CPPInstance* self) { +static PyObject* op_destruct(PyObject* self, PyObject* /*args*/) { // User access to force deletion of the object. Needed in case of a true // garbage collector (like in PyPy), to allow the user control over when // the C++ destructor is called. This method requires that the C++ object // is owned (no-op otherwise). - op_dealloc_nofree(self); + op_dealloc_nofree((CPPInstance*)self); Py_RETURN_NONE; } //= cpyrt object dispatch support ========================================= -static PyObject* op_dispatch(PyObject* self, PyObject* args, - PyObject* /* kdws */) { +static PyObject* op_dispatch(PyObject* self, PyObject* args) { // User-side __dispatch__ method to allow selection of a specific overloaded // method. The actual selection is in the __overload__() method of // CPPOverload. @@ -312,13 +311,14 @@ static PyObject* op_dispatch(PyObject* self, PyObject* args, } //= cpyrt smart pointer support =========================================== -static PyObject* op_get_smartptr(CPPInstance* self) { - if (!self->IsSmart()) { +static PyObject* op_get_smartptr(PyObject* self, PyObject* /*args*/) { + CPPInstance* inst = (CPPInstance*)self; + if (!inst->IsSmart()) { // TODO: more likely should raise Py_RETURN_NONE; } - return cpyrt::BindCppObjectNoCast(self->GetSmartObject(), SMART_TYPE(self), + return cpyrt::BindCppObjectNoCast(inst->GetSmartObject(), SMART_TYPE(inst), CPPInstance::kNoWrapConv); } @@ -335,7 +335,8 @@ Py_ssize_t cpyrt::CPPInstance::ArrayLength() { return (Py_ssize_t)ARRAY_SIZE(this); } -static PyObject* op_reshape(CPPInstance* self, PyObject* shape) { +static PyObject* op_reshape(PyObject* self, PyObject* shape) { + CPPInstance* inst = (CPPInstance*)self; // Allow the user to fix up the actual (type-strided) size of the buffer. if (!PyTuple_Check(shape) || PyTuple_GET_SIZE(shape) != 1) { PyErr_SetString(PyExc_TypeError, "tuple object of size 1 expected"); @@ -348,7 +349,7 @@ static PyObject* op_reshape(CPPInstance* self, PyObject* shape) { return nullptr; } - self->CastToArray(sz); + inst->CastToArray(sz); Py_RETURN_NONE; } @@ -417,26 +418,26 @@ PyCFunction& CPPInstance::ReduceMethod() { return reducer; } -PyObject* op_reduce(PyObject* self, PyObject* args) { +PyObject* op_reduce(PyObject* self, PyObject* /*args*/) { auto& reducer = CPPInstance::ReduceMethod(); if (!reducer) { PyErr_SetString(PyExc_NotImplementedError, ""); return nullptr; } - return reducer(self, args); + return reducer(self, nullptr); } //---------------------------------------------------------------------------- static PyMethodDef op_methods[] = { - {(char*)"__destruct__", (PyCFunction)op_destruct, METH_NOARGS, + {(char*)"__destruct__", op_destruct, METH_NOARGS, (char*)"call the C++ destructor"}, - {(char*)"__dispatch__", (PyCFunction)op_dispatch, METH_VARARGS, + {(char*)"__dispatch__", op_dispatch, METH_VARARGS, (char*)"dispatch to selected overload"}, - {(char*)"__smartptr__", (PyCFunction)op_get_smartptr, METH_NOARGS, + {(char*)"__smartptr__", op_get_smartptr, METH_NOARGS, (char*)"get associated smart pointer, if any"}, - {(char*)"__reduce__", (PyCFunction)op_reduce, METH_NOARGS, + {(char*)"__reduce__", op_reduce, METH_NOARGS, (char*)"reduce method for serialization"}, - {(char*)"__reshape__", (PyCFunction)op_reshape, METH_O, + {(char*)"__reshape__", op_reshape, METH_O, (char*)"cast pointer to 1D array type"}, {(char*)nullptr, nullptr, 0, nullptr}}; diff --git a/src/cpyrt/CPPMethod.cxx b/src/cpyrt/CPPMethod.cxx index 3fe3e37..d1ecba4 100644 --- a/src/cpyrt/CPPMethod.cxx +++ b/src/cpyrt/CPPMethod.cxx @@ -785,7 +785,7 @@ int cpyrt::CPPMethod::GetArgMatchScore(PyObject* args_tuple) { } std::string req_type(cpyrt_PyText_AsString(pItem)); - size_t arg_score = interop::CompareMethodArgType(fMethod, i, req_type); + size_t arg_score = interop::CompareMethodArgType(fMethod); // Method is not compatible if even one argument does not match if (arg_score >= 10) { diff --git a/src/cpyrt/CPPOverload.cxx b/src/cpyrt/CPPOverload.cxx index 49778df..cbe1053 100644 --- a/src/cpyrt/CPPOverload.cxx +++ b/src/cpyrt/CPPOverload.cxx @@ -218,18 +218,20 @@ static inline PyObject* HandleReturn(CPPOverload* pymeth, CPPInstance* im_self, } //= cpyrt method proxy object behaviour =================================== -static PyObject* mp_name(CPPOverload* pymeth, void*) { +static PyObject* mp_name(PyObject* self, void*) { + CPPOverload* pymeth = (CPPOverload*)self; return cpyrt_PyText_FromString(pymeth->GetName().c_str()); } //---------------------------------------------------------------------------- -static PyObject* mp_module(CPPOverload* /* pymeth */, void*) { +static PyObject* mp_module(PyObject*, void*) { Py_INCREF(PyStrings::gThisModule); return PyStrings::gThisModule; } //---------------------------------------------------------------------------- -static PyObject* mp_doc(CPPOverload* pymeth, void*) { +static PyObject* mp_doc(PyObject* self, void*) { + CPPOverload* pymeth = (CPPOverload*)self; if (pymeth->fMethodInfo->fDoc) { Py_INCREF(pymeth->fMethodInfo->fDoc); return pymeth->fMethodInfo->fDoc; @@ -259,7 +261,8 @@ static PyObject* mp_doc(CPPOverload* pymeth, void*) { return doc; } -static int mp_doc_set(CPPOverload* pymeth, PyObject* val, void*) { +static int mp_doc_set(PyObject* self, PyObject* val, void*) { + CPPOverload* pymeth = (CPPOverload*)self; Py_XDECREF(pymeth->fMethodInfo->fDoc); Py_INCREF(val); pymeth->fMethodInfo->fDoc = val; @@ -276,8 +279,8 @@ static int mp_doc_set(CPPOverload* pymeth, PyObject* val, void*) { * 'int ::foo(int a)': ('a',), * 'int ::foo(int a, float b)': ('a', 'b')} */ -static PyObject* mp_func_overloads_names(CPPOverload* pymeth) { - +static PyObject* mp_func_overloads_names(PyObject* self, void*) { + CPPOverload* pymeth = (CPPOverload*)self; const CPPOverload::Methods_t& methods = pymeth->fMethodInfo->fMethods; PyObject* overloads_names_dict = PyDict_New(); @@ -301,8 +304,8 @@ static PyObject* mp_func_overloads_names(CPPOverload* pymeth) { * ('int',), 'return_type': 'int'}, 'int ::foo(int a, float b)': {'input_types': * ('int', 'float'), 'return_type': 'int'}} */ -static PyObject* mp_func_overloads_types(CPPOverload* pymeth) { - +static PyObject* mp_func_overloads_types(PyObject* self, void*) { + CPPOverload* pymeth = (CPPOverload*)self; const CPPOverload::Methods_t& methods = pymeth->fMethodInfo->fMethods; PyObject* overloads_types_dict = PyDict_New(); @@ -316,7 +319,8 @@ static PyObject* mp_func_overloads_types(CPPOverload* pymeth) { } //---------------------------------------------------------------------------- -static PyObject* mp_meth_func(CPPOverload* pymeth, void*) { +static PyObject* mp_meth_func(PyObject* self, void*) { + CPPOverload* pymeth = (CPPOverload*)self; // Create a new method proxy to be returned. CPPOverload* newPyMeth = (CPPOverload*)CPPOverload_Type.tp_alloc(&CPPOverload_Type, 0); @@ -333,7 +337,8 @@ static PyObject* mp_meth_func(CPPOverload* pymeth, void*) { } //---------------------------------------------------------------------------- -static PyObject* mp_meth_self(CPPOverload* pymeth, void*) { +static PyObject* mp_meth_self(PyObject* self, void*) { + CPPOverload* pymeth = (CPPOverload*)self; // Return the bound self, if any; in case of pseudo-function role, pretend // that the data member im_self does not exist. if (IsPseudoFunc(pymeth)) { @@ -350,7 +355,8 @@ static PyObject* mp_meth_self(CPPOverload* pymeth, void*) { } //---------------------------------------------------------------------------- -static PyObject* mp_meth_class(CPPOverload* pymeth, void*) { +static PyObject* mp_meth_class(PyObject* self, void*) { + CPPOverload* pymeth = (CPPOverload*)self; // Return scoping class; in case of pseudo-function role, pretend that there // is no encompassing class (i.e. global scope). if (!IsPseudoFunc(pymeth) && pymeth->fMethodInfo->fMethods.size()) { @@ -366,13 +372,13 @@ static PyObject* mp_meth_class(CPPOverload* pymeth, void*) { } //---------------------------------------------------------------------------- -static PyObject* mp_func_closure(CPPOverload* /* pymeth */, void*) { +static PyObject* mp_func_closure(PyObject*, void*) { // Stub only, to fill out the python function interface. Py_RETURN_NONE; } //---------------------------------------------------------------------------- -static PyObject* mp_func_code(CPPOverload*, void*) { +static PyObject* mp_func_code(PyObject*, void*) { // Code details are used in module inspect to fill out interactive help() // not important for functioning of most code, so not implemented for p3 for // now (TODO) @@ -380,7 +386,8 @@ static PyObject* mp_func_code(CPPOverload*, void*) { } //---------------------------------------------------------------------------- -static PyObject* mp_func_defaults(CPPOverload* pymeth, void*) { +static PyObject* mp_func_defaults(PyObject* self, void*) { + CPPOverload* pymeth = (CPPOverload*)self; // Create a tuple of default values, if there is only one method (otherwise // leave undefined: this is only used by inspect for interactive help()) CPPOverload::Methods_t& methods = pymeth->fMethodInfo->fMethods; @@ -406,7 +413,7 @@ static PyObject* mp_func_defaults(CPPOverload* pymeth, void*) { } //---------------------------------------------------------------------------- -static PyObject* mp_func_globals(CPPOverload* /* pymeth */, void*) { +static PyObject* mp_func_globals(PyObject*, void*) { // Return this function's global dict (hard-wired to be the cppjit module); // used for lookup of names from co_code indexing into co_names. PyObject* pyglobal = PyModule_GetDict(PyImport_AddModule((char*)"cppjit")); @@ -438,19 +445,22 @@ static inline int set_flag(CPPOverload* pymeth, PyObject* value, } //---------------------------------------------------------------------------- -static PyObject* mp_getcreates(CPPOverload* pymeth, void*) { +static PyObject* mp_getcreates(PyObject* self, void*) { + CPPOverload* pymeth = (CPPOverload*)self; // Get '__creates__' boolean, which determines ownership of return values. return PyInt_FromLong((long)IsCreator(pymeth->fMethodInfo->fFlags)); } //---------------------------------------------------------------------------- -static int mp_setcreates(CPPOverload* pymeth, PyObject* value, void*) { +static int mp_setcreates(PyObject* self, PyObject* value, void*) { + CPPOverload* pymeth = (CPPOverload*)self; // Set '__creates__' boolean, which determines ownership of return values. return set_flag(pymeth, value, CallContext::kIsCreator, "__creates__"); } //---------------------------------------------------------------------------- -static PyObject* mp_getmempolicy(CPPOverload* pymeth, void*) { +static PyObject* mp_getmempolicy(PyObject* self, void*) { + CPPOverload* pymeth = (CPPOverload*)self; // Get '_mempolicy' enum, which determines ownership of call arguments. if (pymeth->fMethodInfo->fFlags & CallContext::kUseHeuristics) return PyInt_FromLong(CallContext::kUseHeuristics); @@ -462,7 +472,8 @@ static PyObject* mp_getmempolicy(CPPOverload* pymeth, void*) { } //---------------------------------------------------------------------------- -static int mp_setmempolicy(CPPOverload* pymeth, PyObject* value, void*) { +static int mp_setmempolicy(PyObject* self, PyObject* value, void*) { + CPPOverload* pymeth = (CPPOverload*)self; // Set '_mempolicy' enum, which determines ownership of call arguments. long mempolicy = PyLong_AsLong(value); if (mempolicy == CallContext::kUseHeuristics) { @@ -501,7 +512,8 @@ CPPJIT_BOOLEAN_PROPERTY(useffi, CallContext::kUseFFI, "__useffi__") CPPJIT_BOOLEAN_PROPERTY(sig2exc, CallContext::kProtected, "__sig2exc__") // clang-format on -static PyObject* mp_getcppname(CPPOverload* pymeth, void*) { +static PyObject* mp_getcppname(PyObject* self, void*) { + CPPOverload* pymeth = (CPPOverload*)self; if ((void*)pymeth == (void*)&CPPOverload_Type) return cpyrt_PyText_FromString("CPPOverload_Type"); diff --git a/src/cpyrt/CPPScope.cxx b/src/cpyrt/CPPScope.cxx index fded0d5..7dc2b79 100644 --- a/src/cpyrt/CPPScope.cxx +++ b/src/cpyrt/CPPScope.cxx @@ -614,7 +614,8 @@ static PyObject* meta_reflex(CPPScope* klass, PyObject* args) { // quite what I'd expected of it, so the following pulls in the internal code #include "PyObjectDir27.inc" -static PyObject* meta_dir(CPPScope* klass) { +static PyObject* meta_dir(PyObject* self, PyObject*) { + CPPScope* klass = (CPPScope*)self; // Collect a list of everything (currently) available in the namespace. // The backend can filter by returning empty strings. Special care is // taken for functions, which need not be unique (overloading). @@ -664,7 +665,7 @@ static PyObject* meta_dir(CPPScope* klass) { static PyMethodDef meta_methods[] = { {(char*)"__cpp_reflex__", (PyCFunction)meta_reflex, METH_VARARGS, (char*)"C++ datamember reflection information"}, - {(char*)"__dir__", (PyCFunction)meta_dir, METH_NOARGS, nullptr}, + {(char*)"__dir__", meta_dir, METH_NOARGS, nullptr}, {(char*)nullptr, nullptr, 0, nullptr}}; //----------------------------------------------------------------------------- diff --git a/src/cpyrt/LowLevelViews.cxx b/src/cpyrt/LowLevelViews.cxx index b4b5be1..e2e4715 100644 --- a/src/cpyrt/LowLevelViews.cxx +++ b/src/cpyrt/LowLevelViews.cxx @@ -76,26 +76,23 @@ static void ll_dealloc(cpyrt::LowLevelView* pyobj) { } //---------------------------------------------------------------------------- -#define CPYRT_LL_FLAG_GETSET(name, flag, doc) \ - static PyObject* ll_get##name(cpyrt::LowLevelView* pyobj) { \ - return PyBool_FromLong((long)((intptr_t)pyobj->fBufInfo.internal & flag)); \ - } \ - \ - static int ll_set##name(cpyrt::LowLevelView* pyobj, PyObject* value, \ - void*) { \ - long settrue = PyLong_AsLong(value); \ - if (settrue == -1 && PyErr_Occurred()) { \ - PyErr_SetString(PyExc_ValueError, \ - #doc " should be either True or False"); \ - return -1; \ - } \ - \ - if ((bool)settrue) \ - (intptr_t&)pyobj->fBufInfo.internal |= flag; \ - else \ - (intptr_t&)pyobj->fBufInfo.internal &= ~flag; \ - \ - return 0; \ +#define CPYRT_LL_FLAG_GETSET(name, flag, doc) \ + static PyObject* ll_get##name(PyObject* pyobj, void*) { \ + auto* view = (cpyrt::LowLevelView*)pyobj; \ + return PyBool_FromLong((long)((intptr_t)view->fBufInfo.internal & flag)); \ + } \ + static int ll_set##name(PyObject* pyobj, PyObject* value, void*) { \ + auto* view = (cpyrt::LowLevelView*)pyobj; \ + long settrue = PyLong_AsLong(value); \ + if (settrue == -1 && PyErr_Occurred()) { \ + PyErr_SetString(PyExc_ValueError, #doc " should be either True or False"); \ + return -1; \ + } \ + if ((bool)settrue) \ + (intptr_t&)view->fBufInfo.internal |= flag; \ + else \ + (intptr_t&)view->fBufInfo.internal &= ~flag; \ + return 0; \ } // clang-format off @@ -681,8 +678,9 @@ static PyBufferProcs ll_as_buffer = { }; //--------------------------------------------------------------------------- -static PyObject* ll_shape(cpyrt::LowLevelView* self) { - Py_buffer& view = self->fBufInfo; +static PyObject* ll_shape(PyObject* self, void*) { + cpyrt::LowLevelView* inst = (cpyrt::LowLevelView*)self; + Py_buffer& view = inst->fBufInfo; PyObject* shape = PyTuple_New(view.ndim); for (Py_ssize_t idim = 0; idim < view.ndim; ++idim) @@ -692,8 +690,9 @@ static PyObject* ll_shape(cpyrt::LowLevelView* self) { } //--------------------------------------------------------------------------- -static PyObject* ll_reshape(cpyrt::LowLevelView* self, PyObject* shape) { - // Allow the user to fix up the actual (type-strided) size of the buffer. +static int ll_reshape(PyObject* self, PyObject* shape, void*) { + cpyrt::LowLevelView* inst = (cpyrt::LowLevelView*)self; + if (!PyTuple_Check(shape)) { if (shape) { PyObject* pystr = PyObject_Str(shape); @@ -701,22 +700,22 @@ static PyObject* ll_reshape(cpyrt::LowLevelView* self, PyObject* shape) { PyErr_Format(PyExc_TypeError, "tuple object expected, received %s", cpyrt_PyText_AsStringChecked(pystr)); Py_DECREF(pystr); - return nullptr; + return -1; } } PyErr_SetString(PyExc_TypeError, "tuple object expected"); - return nullptr; + return -1; } - Py_buffer& view = self->fBufInfo; + Py_buffer& view = inst->fBufInfo; // verify size match Py_ssize_t oldsz = 0; for (Py_ssize_t idim = 0; idim < view.ndim; ++idim) { Py_ssize_t nlen = view.shape[idim]; if (nlen == cpyrt::UNKNOWN_SIZE || - nlen == INT_MAX / view.itemsize /* fake 'max' */) { - oldsz = -1; // meaning, unable to check size match + nlen == INT_MAX / view.itemsize) { + oldsz = -1; break; } oldsz += view.shape[idim]; @@ -732,11 +731,11 @@ static PyObject* ll_reshape(cpyrt::LowLevelView* self, PyObject* shape) { "cannot reshape array of size %ld into shape %s", (long)oldsz, cpyrt_PyText_AsString(tas)); Py_DECREF(tas); - return nullptr; + return -1; } } - // reshape + // reshape layout logic... size_t itemsize = view.strides[view.ndim - 1]; if (view.ndim != PyTuple_GET_SIZE(shape)) { PyMem_Free(view.shape); @@ -750,7 +749,7 @@ static PyObject* ll_reshape(cpyrt::LowLevelView* self, PyObject* shape) { for (Py_ssize_t idim = 0; idim < PyTuple_GET_SIZE(shape); ++idim) { Py_ssize_t nlen = PyInt_AsSsize_t(PyTuple_GET_ITEM(shape, idim)); if (nlen == -1 && PyErr_Occurred()) - return nullptr; + return -1; if (idim == 0) view.len = nlen * view.itemsize; @@ -758,14 +757,21 @@ static PyObject* ll_reshape(cpyrt::LowLevelView* self, PyObject* shape) { view.shape[idim] = nlen; } - set_strides(view, itemsize, false /* by definition not fixed */); + set_strides(view, itemsize, false); + return 0; // Success +} + +static PyObject* ll_reshape(PyObject* self, PyObject* shape) { + if (ll_reshape(self, shape, nullptr) < 0) { + return nullptr; + } Py_RETURN_NONE; } //--------------------------------------------------------------------------- -static PyObject* ll_array(cpyrt::LowLevelView* self, PyObject* args, - PyObject* kwds) { +static PyObject* ll_array(PyObject* self, PyObject* args) { + cpyrt::LowLevelView* inst = (cpyrt::LowLevelView*)self; // Construct a numpy array from the lowlevelview (w/o copy if possible); this // uses the Python methods to avoid depending on numpy directly @@ -775,17 +781,6 @@ static PyObject* ll_array(cpyrt::LowLevelView* self, PyObject* args, return nullptr; bool docopy = false; - if (kwds) { - PyObject* pycp = PyObject_GetItem(kwds, cpyrt::PyStrings::gCopy); - if (!pycp) { - PyErr_SetString(PyExc_TypeError, - "__array__ only supports the \"copy\" keyword"); - return nullptr; - } - - docopy = PyObject_IsTrue(pycp); - Py_DECREF(pycp); - } if (!docopy) { // view requested // expect possible dtype from the arguments, otherwise take it from the type @@ -793,7 +788,7 @@ static PyObject* ll_array(cpyrt::LowLevelView* self, PyObject* args, PyObject* dtype; if (!args || PyTuple_GET_SIZE(args) != 1) { PyObject* npdtype = PyObject_GetAttr(npmod, cpyrt::PyStrings::gDType); - PyObject* typecode = ll_typecode(self, nullptr); + PyObject* typecode = ll_typecode(inst, nullptr); dtype = PyObject_CallFunctionObjArgs(npdtype, typecode, nullptr); Py_DECREF(typecode); Py_DECREF(npdtype); @@ -807,7 +802,7 @@ static PyObject* ll_array(cpyrt::LowLevelView* self, PyObject* args, PyObject* npfrombuf = PyObject_GetAttr(npmod, cpyrt::PyStrings::gFromBuffer); - PyObject* view = PyObject_CallFunctionObjArgs(npfrombuf, (PyObject*)self, + PyObject* view = PyObject_CallFunctionObjArgs(npfrombuf, (PyObject*)inst, dtype, nullptr); Py_DECREF(dtype); Py_DECREF(npfrombuf); @@ -817,7 +812,7 @@ static PyObject* ll_array(cpyrt::LowLevelView* self, PyObject* args, } else { // copy requested PyObject* npcopy = PyObject_GetAttr(npmod, cpyrt::PyStrings::gCopy); PyObject* newarr = - PyObject_CallFunctionObjArgs(npcopy, (PyObject*)self, nullptr); + PyObject_CallFunctionObjArgs(npcopy, (PyObject*)inst, nullptr); Py_DECREF(npcopy); return newarr; @@ -828,9 +823,10 @@ static PyObject* ll_array(cpyrt::LowLevelView* self, PyObject* args, } //--------------------------------------------------------------------------- -static PyObject* ll_as_string(cpyrt::LowLevelView* self) { +static PyObject* ll_as_string(PyObject* self, PyObject* /*args*/) { + cpyrt::LowLevelView* inst = (cpyrt::LowLevelView*)self; // Interpret memory as a null-terminated char string. - Py_buffer& view = self->fBufInfo; + Py_buffer& view = inst->fBufInfo; if (strcmp(view.format, "b") != 0 || view.ndim != 1) { PyErr_Format( @@ -840,19 +836,19 @@ static PyObject* ll_as_string(cpyrt::LowLevelView* self) { return nullptr; } - char* buf = (char*)self->get_buf(); + char* buf = (char*)inst->get_buf(); size_t sz = strnlen(buf, (size_t)view.shape[0]); return cpyrt_PyText_FromStringAndSize(buf, sz); } //--------------------------------------------------------------------------- static PyMethodDef ll_methods[] = { - {(char*)"reshape", (PyCFunction)ll_reshape, METH_O, + {(char*)"reshape", ll_reshape, METH_O, (char*)"change the shape (not layout) of the low level view"}, - {(char*)"as_string", (PyCFunction)ll_as_string, METH_NOARGS, + {(char*)"as_string", ll_as_string, METH_NOARGS, (char*)"interpret memory as a null-terminated char string and return " "Python str"}, - {(char*)"__array__", (PyCFunction)ll_array, METH_VARARGS | METH_KEYWORDS, + {(char*)"__array__", ll_array, METH_VARARGS, (char*)"return a numpy array from the low level view"}, {(char*)nullptr, nullptr, 0, nullptr}}; diff --git a/src/cpyrt/MemoryRegulator.cxx b/src/cpyrt/MemoryRegulator.cxx index 6ea7671..69d45ea 100644 --- a/src/cpyrt/MemoryRegulator.cxx +++ b/src/cpyrt/MemoryRegulator.cxx @@ -52,7 +52,9 @@ struct Initcpyrt_NoneType_t { cpyrt_NoneType.tp_repr = Py_TYPE(Py_None)->tp_repr; cpyrt_NoneType.tp_richcompare = (richcmpfunc)&Initcpyrt_NoneType_t::RichCompare; - cpyrt_NoneType.tp_hash = (hashfunc)&Initcpyrt_NoneType_t::PtrHash; + + // Assigned directly without a cast + cpyrt_NoneType.tp_hash = PtrHash; cpyrt_NoneType.tp_as_mapping = &cpyrt_NoneType_mapping; @@ -60,7 +62,8 @@ struct Initcpyrt_NoneType_t { } static void DeAlloc(PyObject* pyobj) { Py_TYPE(pyobj)->tp_free(pyobj); } - static int PtrHash(PyObject* pyobj) { return (int)ptrdiff_t(pyobj); } + // Return Py_hash_t instead of int to match hashfunc signature natively + static Py_hash_t PtrHash(PyObject* pyobj) { return (Py_hash_t)pyobj; } static PyObject* RichCompare(PyObject*, PyObject* other, int opid) { return PyObject_RichCompare(other, Py_None, opid); diff --git a/src/cpyrt/PyStrings.cxx b/src/cpyrt/PyStrings.cxx index f255244..2fd244a 100644 --- a/src/cpyrt/PyStrings.cxx +++ b/src/cpyrt/PyStrings.cxx @@ -166,7 +166,7 @@ bool cpyrt::CreatePyStrings() { } //----------------------------------------------------------------------------- -PyObject* cpyrt::DestroyPyStrings() { +PyObject* cpyrt::DestroyPyStrings(PyObject* Py_UNUSED(args1), PyObject* Py_UNUSED(args2)) { // Remove all cached python strings. Py_DECREF(PyStrings::gBases); PyStrings::gBases = nullptr; diff --git a/src/cpyrt/PyStrings.h b/src/cpyrt/PyStrings.h index 072dddd..7bc4a70 100644 --- a/src/cpyrt/PyStrings.h +++ b/src/cpyrt/PyStrings.h @@ -84,7 +84,7 @@ extern PyObject* gFromBuffer; } // namespace PyStrings bool CreatePyStrings(); -PyObject* DestroyPyStrings(); + PyObject* DestroyPyStrings(PyObject* Py_UNUSED(args1), PyObject* Py_UNUSED(args2)); } // namespace cppjit::cpyrt diff --git a/src/cpyrt/Pythonize.cxx b/src/cpyrt/Pythonize.cxx index 3e6b874..bc625fc 100644 --- a/src/cpyrt/Pythonize.cxx +++ b/src/cpyrt/Pythonize.cxx @@ -209,7 +209,7 @@ PyObject* FollowGetAttr(PyObject* self, PyObject* name) { } //- pointer checking bool converter ------------------------------------------- -PyObject* NullCheckBool(PyObject* self) { +PyObject* NullCheckBool(PyObject* self, PyObject* Py_UNUSED(args)) { if (!CPPInstance_Check(self)) { PyErr_SetString(PyExc_TypeError, "C++ object proxy expected"); return nullptr; @@ -438,7 +438,7 @@ static bool FillVector(PyObject* vecin, PyObject* args, ItemGetter* getter) { return fill_ok; } -PyObject* VectorIAdd(PyObject* self, PyObject* args, PyObject* /* kwds */) { +PyObject* VectorIAdd(PyObject* self, PyObject* args) { // Implement fast __iadd__ on std::vector (generic __iadd__ is in Python) ItemGetter* getter = GetGetter(args); @@ -474,7 +474,7 @@ PyObject* VectorIAdd(PyObject* self, PyObject* args, PyObject* /* kwds */) { return nullptr; // error already set } -PyObject* VectorInit(PyObject* self, PyObject* args, PyObject* /* kwds */) { +PyObject* VectorInit(PyObject* self, PyObject* args) { // Specialized vector constructor to allow construction from containers; // allowing such construction from initializer_list instead would possible, // but can be error-prone. This use case is common enough for std::vector to @@ -538,10 +538,10 @@ PyObject* VectorData(PyObject* self, PyObject*) { } //--------------------------------------------------------------------------- -PyObject* VectorArray(PyObject* self, PyObject* args, PyObject* kwargs) { +PyObject* VectorArray(PyObject* self, PyObject* args) { PyObject* pydata = VectorData(self, nullptr); PyObject* arrcall = PyObject_GetAttr(pydata, PyStrings::gArray); - PyObject* newarr = PyObject_Call(arrcall, args, kwargs); + PyObject* newarr = PyObject_Call(arrcall, args, nullptr); Py_DECREF(arrcall); Py_DECREF(pydata); return newarr; @@ -778,7 +778,7 @@ PyObject* VectorBoolSetItem(CPPInstance* self, PyObject* args) { } //- array behavior as primitives ---------------------------------------------- -PyObject* ArrayInit(PyObject* self, PyObject* args, PyObject* /* kwds */) { +PyObject* ArrayInit(PyObject* self, PyObject* args) { // std::array is normally only constructed using aggregate initialization, // which is a concept that does not exist in python, so use this custom // constructor to to fill the array using setitem @@ -867,7 +867,7 @@ static PyObject* MapFromPairs(PyObject* self, PyObject* pairs) { return result; } -PyObject* MapInit(PyObject* self, PyObject* args, PyObject* /* kwds */) { +PyObject* MapInit(PyObject* self, PyObject* args) { // Specialized map constructor to allow construction from mapping containers // and from tuples of pairs ("initializer_list style"). @@ -941,7 +941,7 @@ PyObject* STLContainsWithFind(PyObject* self, PyObject* obj) { } //- set behavior as primitives ------------------------------------------------ -PyObject* SetInit(PyObject* self, PyObject* args, PyObject* /* kwds */) { +PyObject* SetInit(PyObject* self, PyObject* args) { // Specialized set constructor to allow construction from Python sets. if (PyTuple_GET_SIZE(args) == 1 && PySet_Check(PyTuple_GET_ITEM(args, 0))) { PyObject* pyset = PyTuple_GET_ITEM(args, 0); @@ -993,9 +993,9 @@ static const ptrdiff_t PS_END_ADDR = 7; // non-aligned address, so no clash static const ptrdiff_t PS_FLAG_ADDR = 11; // id. static const ptrdiff_t PS_COLL_ADDR = 13; // id. -PyObject* STLIterNext(PyObject* self); // defined below; used by STLSequenceIter +PyObject* STLIterNext(PyObject* self, PyObject* Py_UNUSED(args)); // defined below; used by STLSequenceIter -PyObject* LLSequenceIter(PyObject* self) { +PyObject* LLSequenceIter(PyObject* self, PyObject* Py_UNUSED(args)) { // Implement python's __iter__ for low level views used through STL-type // begin()/end() PyObject* iter = PyObject_CallMethodNoArgs(self, PyStrings::gBegin); @@ -1022,7 +1022,21 @@ PyObject* LLSequenceIter(PyObject* self) { return nullptr; } -PyObject* STLSequenceIter(PyObject* self) { +static PyObject* my_iter(PyObject* self, PyObject* Py_UNUSED(args)) { + return PyObject_SelfIter(self); +} + +static PyObject* STLIterNextAdapter(PyObject *self) +{ + return STLIterNext(self, nullptr); +} + +static PyObject* LLSequenceIterAdapter(PyObject *self) +{ + return LLSequenceIter(self, nullptr); +} + +PyObject* STLSequenceIter(PyObject* self, PyObject* Py_UNUSED(args)) { // Implement python's __iter__ for std::iterator<>s PyObject* iter = PyObject_CallMethodNoArgs(self, PyStrings::gBegin); if (iter) { @@ -1040,13 +1054,13 @@ PyObject* STLSequenceIter(PyObject* self) { PyTypeObject* itype = Py_TYPE(iter); if (!PyIter_Check(iter)) { // no tp_iternext, or the // _PyObject_NextNotImplemented sentinel - itype->tp_iternext = (iternextfunc)STLIterNext; + itype->tp_iternext = (iternextfunc)STLIterNextAdapter; Utility::AddToClass((PyObject*)itype, CPPJIT__next__, - (PyCFunction)STLIterNext, METH_NOARGS); + STLIterNext, METH_NOARGS); if (!itype->tp_iter) { itype->tp_iter = (getiterfunc)PyObject_SelfIter; Utility::AddToClass((PyObject*)itype, "__iter__", - (PyCFunction)PyObject_SelfIter, METH_NOARGS); + my_iter, METH_NOARGS); } PyType_Modified(itype); } @@ -1073,9 +1087,14 @@ PyObject* STLSequenceIter(PyObject* self) { return iter; } +static PyObject* STLSequenceIterAdapter(PyObject *self) +{ + return STLSequenceIter(self, nullptr); +} + //- generic iterator support over a sequence with operator[] and size --------- //----------------------------------------------------------------------------- -static PyObject* index_iter(PyObject* c) { +static PyObject* index_iter(PyObject* c, PyObject* Py_UNUSED(args)) { indexiterobject* ii = PyObject_GC_New(indexiterobject, &IndexIter_Type); if (!ii) return nullptr; @@ -1089,6 +1108,11 @@ static PyObject* index_iter(PyObject* c) { return (PyObject*)ii; } +static PyObject* index_iterAdapter(PyObject *self) +{ + return index_iter(self, nullptr); +} + //- safe indexing for STL-like vector w/o iterator dictionaries --------------- /* replaced by indexiterobject iteration, but may still have some future use ... PyObject* CheckedGetItem(PyObject* self, PyObject* obj) @@ -1145,7 +1169,7 @@ PyObject* PairUnpack(PyObject* self, PyObject* pyindex) { PyObject* ReturnTwo(CPPInstance*, PyObject*) { return PyInt_FromLong(2); } //- shared/unique_ptr behavior ----------------------------------------------- -PyObject* SmartPtrInit(PyObject* self, PyObject* args, PyObject* /* kwds */) { +PyObject* SmartPtrInit(PyObject* self, PyObject* args) { // since the shared/unique pointer will take ownership, we need to relinquish // it PyObject* realInit = PyObject_GetAttr(self, PyStrings::gRealInit); @@ -1198,7 +1222,7 @@ static inline PyObject* cpyrt_PyString_FromCppString(std::wstring_view s, return nullptr; \ } \ \ - PyObject* name##StringStr(PyObject* self) { \ + PyObject* name##StringStr(PyObject* self, PyObject* Py_UNUSED(args)) { \ PyObject* pyobj = name##StringGetData(self, false); \ if (!pyobj) { \ /* do a native conversion to make printing possible (debatable) */ \ @@ -1212,11 +1236,11 @@ static inline PyObject* cpyrt_PyString_FromCppString(std::wstring_view s, return pyobj; \ } \ \ - PyObject* name##StringBytes(PyObject* self) { \ + PyObject* name##StringBytes(PyObject* self, PyObject* Py_UNUSED(args)) { \ return name##StringGetData(self, true); \ } \ \ - PyObject* name##StringRepr(PyObject* self) { \ + PyObject* name##StringRepr(PyObject* self, PyObject* Py_UNUSED(args)) { \ PyObject* data = name##StringGetData(self, true); \ if (data) { \ PyObject* repr = PyObject_Repr(data); \ @@ -1278,16 +1302,15 @@ static inline std::string* GetSTLString(CPPInstance* self) { return obj; } -PyObject* STLStringDecode(CPPInstance* self, PyObject* args, PyObject* kwds) { - std::string* obj = GetSTLString(self); +PyObject* STLStringDecode(PyObject* self, PyObject* args) { + CPPInstance* inst = (CPPInstance*)self; + std::string* obj = GetSTLString(inst); if (!obj) return nullptr; - char* keywords[] = {(char*)"encoding", (char*)"errors", (char*)nullptr}; const char* encoding = nullptr; const char* errors = nullptr; - if (!PyArg_ParseTupleAndKeywords(args, kwds, const_cast("s|s"), - keywords, &encoding, &errors)) + if (!PyArg_ParseTuple(args, "s|s", &encoding, &errors)) return nullptr; return PyUnicode_Decode(obj->data(), obj->size(), encoding, errors); @@ -1309,9 +1332,9 @@ PyObject* STLStringContains(CPPInstance* self, PyObject* pyobj) { Py_RETURN_FALSE; } -PyObject* STLStringReplace(CPPInstance* self, PyObject* args, - PyObject* /*kwds*/) { - std::string* obj = GetSTLString(self); +PyObject* STLStringReplace(PyObject* self, PyObject* args) { + CPPInstance* inst = (CPPInstance*)self; + std::string* obj = GetSTLString(inst); if (!obj) return nullptr; @@ -1330,7 +1353,7 @@ PyObject* STLStringReplace(CPPInstance* self, PyObject* args, } PyObject* cppreplace = - PyObject_GetAttrString((PyObject*)self, (char*)"__cpp_replace"); + PyObject_GetAttrString((PyObject*)inst, (char*)"__cpp_replace"); if (cppreplace) { PyObject* result = PyObject_Call(cppreplace, args, nullptr); Py_DECREF(cppreplace); @@ -1343,14 +1366,14 @@ PyObject* STLStringReplace(CPPInstance* self, PyObject* args, } #define CPYRT_STRING_FINDMETHOD(name, cppname, pyname) \ - PyObject* STLString##name(CPPInstance* self, PyObject* args, \ - PyObject* /*kwds*/) { \ - std::string* obj = GetSTLString(self); \ + PyObject* STLString##name(PyObject* self, PyObject* args) { \ + CPPInstance* inst = (CPPInstance*) self; \ + std::string* obj = GetSTLString(inst); \ if (!obj) \ return nullptr; \ \ PyObject* cppmeth = \ - PyObject_GetAttrString((PyObject*)self, (char*)#cppname); \ + PyObject_GetAttrString((PyObject*)inst, (char*)#cppname); \ if (cppmeth) { \ PyObject* result = PyObject_Call(cppmeth, args, nullptr); \ Py_DECREF(cppmeth); \ @@ -1392,7 +1415,7 @@ PyObject* STLStringGetAttr(CPPInstance* self, PyObject* attr_name) { return attr; } -PyObject* UTF8Repr(PyObject* self) { +PyObject* UTF8Repr(PyObject* self, PyObject* Py_UNUSED(args)) { // force C++ string types conversion to Python str per Python __repr__ // requirements PyObject* res = PyObject_CallMethodNoArgs(self, PyStrings::gCppRepr); @@ -1403,7 +1426,7 @@ PyObject* UTF8Repr(PyObject* self) { return str_res; } -PyObject* UTF8Str(PyObject* self) { +PyObject* UTF8Str(PyObject* self, PyObject* Py_UNUSED(args)) { // force C++ string types conversion to Python str per Python __str__ // requirements PyObject* res = PyObject_CallMethodNoArgs(self, PyStrings::gCppStr); @@ -1424,7 +1447,7 @@ Py_hash_t STLStringHash(PyObject* self) { } //- string_view behavior as primitive ---------------------------------------- -PyObject* StringViewInit(PyObject* self, PyObject* args, PyObject* /* kwds */) { +PyObject* StringViewInit(PyObject* self, PyObject* args) { // if constructed from a Python unicode object, the constructor will convert // it to a temporary byte string, which is likely to go out of scope too soon; // so buffer it as needed @@ -1464,7 +1487,7 @@ PyObject* StringViewInit(PyObject* self, PyObject* args, PyObject* /* kwds */) { } //- STL iterator behavior ---------------------------------------------------- -PyObject* STLIterNext(PyObject* self) { +PyObject* STLIterNext(PyObject* self, PyObject* Py_UNUSED(args)) { // Python iterator protocol __next__ for STL forward iterators. bool mustIncrement = true; PyObject* last = nullptr; @@ -1536,7 +1559,7 @@ PyObject* STLIterNext(PyObject* self) { COMPLEX_METH_GETSET(real, PyStrings::gCppReal) COMPLEX_METH_GETSET(imag, PyStrings::gCppImag) -static PyObject* ComplexComplex(PyObject* self) { +static PyObject* ComplexComplex(PyObject* self, PyObject* Py_UNUSED(args)) { PyObject* real = PyObject_CallMethodNoArgs(self, PyStrings::gCppReal); if (!real) return nullptr; @@ -1556,7 +1579,7 @@ static PyObject* ComplexComplex(PyObject* self) { return PyComplex_FromDoubles(r, i); } -static PyObject* ComplexRepr(PyObject* self) { +static PyObject* ComplexRepr(PyObject* self, PyObject* Py_UNUSED(args)) { PyObject* real = PyObject_CallMethodNoArgs(self, PyStrings::gCppReal); if (!real) return nullptr; @@ -1608,9 +1631,10 @@ static int ComplexDImagSet(CPPInstance* self, PyObject* value, void*) { PyGetSetDef ComplexDImag{(char*)"imag", (getter)ComplexDImagGet, (setter)ComplexDImagSet, nullptr, nullptr}; -static PyObject* ComplexDComplex(CPPInstance* self) { - double r = ((std::complex*)self->GetObject())->real(); - double i = ((std::complex*)self->GetObject())->imag(); +static PyObject* ComplexDComplex(PyObject* self, PyObject* Py_UNUSED(args)) { + CPPInstance* inst = (CPPInstance*)self; + double r = ((std::complex*)inst->GetObject())->real(); + double i = ((std::complex*)inst->GetObject())->imag(); return PyComplex_FromDoubles(r, i); } @@ -1671,7 +1695,7 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { // for pre-check of nullptr for boolean types if (HasAttrDirect(pyclass, PyStrings::gCppBool)) { const char* pybool_name = "__bool__"; - Utility::AddToClass(pyclass, pybool_name, (PyCFunction)NullCheckBool, + Utility::AddToClass(pyclass, pybool_name, NullCheckBool, METH_NOARGS); } @@ -1708,8 +1732,8 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { if (isIterator) { // install iterator protocol a la STL - ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)STLSequenceIter; - Utility::AddToClass(pyclass, "__iter__", (PyCFunction)STLSequenceIter, + ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)STLSequenceIterAdapter; + Utility::AddToClass(pyclass, "__iter__", STLSequenceIter, METH_NOARGS); } else { // still okay if this is some pointer type of builtin persuasion @@ -1718,9 +1742,9 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { std::string resolved = interop::ResolveName(resname); if (resolved.back() == '*' && interop::IsBuiltin(resolved.substr(0, resolved.size() - 1))) { - ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)LLSequenceIter; + ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)LLSequenceIterAdapter; Utility::AddToClass(pyclass, "__iter__", - (PyCFunction)LLSequenceIter, METH_NOARGS); + LLSequenceIter, METH_NOARGS); } } } @@ -1733,8 +1757,8 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { // if beyond size()) works in some cases but would mess up if operator[] // is meant to implement an associative container. So, this has to be // implemented as an iterator protocol. - ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)index_iter; - Utility::AddToClass(pyclass, "__iter__", (PyCFunction)index_iter, + ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)index_iterAdapter; + Utility::AddToClass(pyclass, "__iter__", index_iter, METH_NOARGS); } } @@ -1780,14 +1804,14 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { if (HasAttrDirect(pyclass, PyStrings::gRepr, true)) { // guarantee that the result of __repr__ is a Python string Utility::AddToClass(pyclass, "__cpp_repr", "__repr__"); - Utility::AddToClass(pyclass, "__repr__", (PyCFunction)UTF8Repr, + Utility::AddToClass(pyclass, "__repr__", UTF8Repr, METH_NOARGS); } if (HasAttrDirect(pyclass, PyStrings::gStr, true)) { // guarantee that the result of __str__ is a Python string Utility::AddToClass(pyclass, "__cpp_str", "__str__"); - Utility::AddToClass(pyclass, "__str__", (PyCFunction)UTF8Str, METH_NOARGS); + Utility::AddToClass(pyclass, "__str__", UTF8Str, METH_NOARGS); } if (interop::IsAggregate(((CPPClass*)pyclass)->fCppType) && @@ -1894,7 +1918,7 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { } else { // constructor that takes python collections Utility::AddToClass(pyclass, "__real_init", "__init__"); - Utility::AddToClass(pyclass, "__init__", (PyCFunction)VectorInit, + Utility::AddToClass(pyclass, "__init__", VectorInit, METH_VARARGS | METH_KEYWORDS); // data with size @@ -1902,8 +1926,8 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { Utility::AddToClass(pyclass, "data", (PyCFunction)VectorData); // numpy array conversion - Utility::AddToClass(pyclass, "__array__", (PyCFunction)VectorArray, - METH_VARARGS | METH_KEYWORDS /* unused */); + Utility::AddToClass(pyclass, "__array__", VectorArray, + METH_VARARGS); // checked getitem if (HasAttrDirect(pyclass, PyStrings::gLen)) { @@ -1916,7 +1940,7 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)vector_iter; // optimized __iadd__ - Utility::AddToClass(pyclass, "__iadd__", (PyCFunction)VectorIAdd, + Utility::AddToClass(pyclass, "__iadd__", VectorIAdd, METH_VARARGS | METH_KEYWORDS); // helpers for iteration @@ -1945,7 +1969,7 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { else if (IsTemplatedSTLClass(name, "array")) { // constructor that takes python associative collections Utility::AddToClass(pyclass, "__real_init", "__init__"); - Utility::AddToClass(pyclass, "__init__", (PyCFunction)ArrayInit, + Utility::AddToClass(pyclass, "__init__", ArrayInit, METH_VARARGS | METH_KEYWORDS); } @@ -1953,7 +1977,7 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { IsTemplatedSTLClass(name, "unordered_map")) { // constructor that takes python associative collections Utility::AddToClass(pyclass, "__real_init", "__init__"); - Utility::AddToClass(pyclass, "__init__", (PyCFunction)MapInit, + Utility::AddToClass(pyclass, "__init__", MapInit, METH_VARARGS | METH_KEYWORDS); // From C++20, std::map/unordered_map have a native contains() that the // generic contains->__contains__ mapping above will pick up. Strong-types @@ -1968,7 +1992,7 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { else if (IsTemplatedSTLClass(name, "set")) { // constructor that takes python associative collections Utility::AddToClass(pyclass, "__real_init", "__init__"); - Utility::AddToClass(pyclass, "__init__", (PyCFunction)SetInit, + Utility::AddToClass(pyclass, "__init__", SetInit, METH_VARARGS | METH_KEYWORDS); // From C++20, std::set has a native contains() that the generic // contains->__contains__ mapping above will pick up. Strong-types @@ -1989,18 +2013,18 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { if (IsTemplatedSTLClass(name, "shared_ptr") || IsTemplatedSTLClass(name, "unique_ptr")) { Utility::AddToClass(pyclass, "__real_init", "__init__"); - Utility::AddToClass(pyclass, "__init__", (PyCFunction)SmartPtrInit, + Utility::AddToClass(pyclass, "__init__", SmartPtrInit, METH_VARARGS | METH_KEYWORDS); } else if (!((PyTypeObject*)pyclass)->tp_iter && (name.find("iterator") != std::string::npos || gIteratorTypes.find(name) != gIteratorTypes.end())) { - ((PyTypeObject*)pyclass)->tp_iternext = (iternextfunc)STLIterNext; - Utility::AddToClass(pyclass, CPPJIT__next__, (PyCFunction)STLIterNext, + ((PyTypeObject*)pyclass)->tp_iternext = (iternextfunc)STLIterNextAdapter; + Utility::AddToClass(pyclass, CPPJIT__next__, STLIterNext, METH_NOARGS); ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)PyObject_SelfIter; - Utility::AddToClass(pyclass, "__iter__", (PyCFunction)PyObject_SelfIter, + Utility::AddToClass(pyclass, "__iter__", my_iter, METH_NOARGS); } @@ -2008,11 +2032,11 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { name == "std::__1::basic_string" || // libc++ inline namespace name == "std::string") { // typedef preserved by GetScopedFinalName // on libc++ - Utility::AddToClass(pyclass, "__repr__", (PyCFunction)STLStringRepr, + Utility::AddToClass(pyclass, "__repr__", STLStringRepr, METH_NOARGS); - Utility::AddToClass(pyclass, "__str__", (PyCFunction)STLStringStr, + Utility::AddToClass(pyclass, "__str__", STLStringStr, METH_NOARGS); - Utility::AddToClass(pyclass, "__bytes__", (PyCFunction)STLStringBytes, + Utility::AddToClass(pyclass, "__bytes__", STLStringBytes, METH_NOARGS); Utility::AddToClass(pyclass, "__cmp__", (PyCFunction)STLStringCompare, METH_O); @@ -2026,16 +2050,16 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { // wrongly dropped it when built with -std=c++2c (__cplusplus == 202400L). Utility::AddToClass(pyclass, "__contains__", (PyCFunction)STLStringContains, METH_O); - Utility::AddToClass(pyclass, "decode", (PyCFunction)STLStringDecode, - METH_VARARGS | METH_KEYWORDS); + Utility::AddToClass(pyclass, "decode", STLStringDecode, + METH_VARARGS); Utility::AddToClass(pyclass, "__cpp_find", "find"); - Utility::AddToClass(pyclass, "find", (PyCFunction)STLStringFind, + Utility::AddToClass(pyclass, "find", STLStringFind, METH_VARARGS | METH_KEYWORDS); Utility::AddToClass(pyclass, "__cpp_rfind", "rfind"); - Utility::AddToClass(pyclass, "rfind", (PyCFunction)STLStringRFind, + Utility::AddToClass(pyclass, "rfind", STLStringRFind, METH_VARARGS | METH_KEYWORDS); Utility::AddToClass(pyclass, "__cpp_replace", "replace"); - Utility::AddToClass(pyclass, "replace", (PyCFunction)STLStringReplace, + Utility::AddToClass(pyclass, "replace", STLStringReplace, METH_VARARGS | METH_KEYWORDS); Utility::AddToClass(pyclass, "__getattr__", (PyCFunction)STLStringGetAttr, METH_O); @@ -2050,9 +2074,9 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { name == "std::string_view") { // typedef preserved by // GetScopedFinalName on libc++ Utility::AddToClass(pyclass, "__real_init", "__init__"); - Utility::AddToClass(pyclass, "__init__", (PyCFunction)StringViewInit, + Utility::AddToClass(pyclass, "__init__", StringViewInit, METH_VARARGS | METH_KEYWORDS); - Utility::AddToClass(pyclass, "__bytes__", (PyCFunction)STLViewStringBytes, + Utility::AddToClass(pyclass, "__bytes__", STLViewStringBytes, METH_NOARGS); Utility::AddToClass(pyclass, "__cmp__", (PyCFunction)STLViewStringCompare, METH_O); @@ -2060,9 +2084,9 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { METH_O); Utility::AddToClass(pyclass, "__ne__", (PyCFunction)STLViewStringIsNotEqual, METH_O); - Utility::AddToClass(pyclass, "__repr__", (PyCFunction)STLViewStringRepr, + Utility::AddToClass(pyclass, "__repr__", STLViewStringRepr, METH_NOARGS); - Utility::AddToClass(pyclass, "__str__", (PyCFunction)STLViewStringStr, + Utility::AddToClass(pyclass, "__str__", STLViewStringStr, METH_NOARGS); } @@ -2071,11 +2095,11 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { name == "std::__1::basic_string,std::__1::allocator >" || name == "std::wstring") { - Utility::AddToClass(pyclass, "__repr__", (PyCFunction)STLWStringRepr, + Utility::AddToClass(pyclass, "__repr__", STLWStringRepr, METH_NOARGS); - Utility::AddToClass(pyclass, "__str__", (PyCFunction)STLWStringStr, + Utility::AddToClass(pyclass, "__str__", STLWStringStr, METH_NOARGS); - Utility::AddToClass(pyclass, "__bytes__", (PyCFunction)STLWStringBytes, + Utility::AddToClass(pyclass, "__bytes__", STLWStringBytes, METH_NOARGS); Utility::AddToClass(pyclass, "__cmp__", (PyCFunction)STLWStringCompare, METH_O); @@ -2094,9 +2118,9 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { PyObject_SetAttrString( pyclass, "imag", PyDescr_NewGetSet((PyTypeObject*)pyclass, &ComplexDImag)); - Utility::AddToClass(pyclass, "__complex__", (PyCFunction)ComplexDComplex, + Utility::AddToClass(pyclass, "__complex__", ComplexDComplex, METH_NOARGS); - Utility::AddToClass(pyclass, "__repr__", (PyCFunction)ComplexRepr, + Utility::AddToClass(pyclass, "__repr__", ComplexRepr, METH_NOARGS); } @@ -2109,9 +2133,9 @@ bool cpyrt::Pythonize(PyObject* pyclass, interop::TCppScope_t scope) { PyObject_SetAttrString( pyclass, "imag", PyDescr_NewGetSet((PyTypeObject*)pyclass, &imagComplex)); - Utility::AddToClass(pyclass, "__complex__", (PyCFunction)ComplexComplex, + Utility::AddToClass(pyclass, "__complex__", ComplexComplex, METH_NOARGS); - Utility::AddToClass(pyclass, "__repr__", (PyCFunction)ComplexRepr, + Utility::AddToClass(pyclass, "__repr__", ComplexRepr, METH_NOARGS); } diff --git a/src/cpyrt/cpyrtModule.cxx b/src/cpyrt/cpyrtModule.cxx index b2c0733..93a8778 100644 --- a/src/cpyrt/cpyrtModule.cxx +++ b/src/cpyrt/cpyrtModule.cxx @@ -528,7 +528,7 @@ static void* GetCPPInstanceAddress(const char* fname, PyObject* args, } //---------------------------------------------------------------------------- -static PyObject* addressof(PyObject* /* dummy */, PyObject* args, +static PyObject* addressof(PyObject* args, PyObject* kwds) { // Return object proxy address as a value (cppjit-style), or the same for an // array. @@ -593,7 +593,7 @@ static PyObject* addressof(PyObject* /* dummy */, PyObject* args, } //---------------------------------------------------------------------------- -static PyObject* AsCObject(PyObject* /* unused */, PyObject* args, +static PyObject* AsCObject(PyObject* args, PyObject* kwds) { // Return object proxy as an opaque CObject. void* addr = GetCPPInstanceAddress("as_cobject", args, kwds); @@ -603,7 +603,7 @@ static PyObject* AsCObject(PyObject* /* unused */, PyObject* args, } //---------------------------------------------------------------------------- -static PyObject* AsCapsule(PyObject* /* unused */, PyObject* args, +static PyObject* AsCapsule(PyObject* args, PyObject* kwds) { // Return object proxy as an opaque PyCapsule. void* addr = GetCPPInstanceAddress("as_capsule", args, kwds); @@ -613,7 +613,7 @@ static PyObject* AsCapsule(PyObject* /* unused */, PyObject* args, } //---------------------------------------------------------------------------- -static PyObject* AsCTypes(PyObject* /* unused */, PyObject* args, +static PyObject* AsCTypes(PyObject* args, PyObject* kwds) { // Return object proxy as a ctypes c_void_p void* addr = GetCPPInstanceAddress("as_ctypes", args, kwds); @@ -677,7 +677,7 @@ static PyObject* AsMemoryView(PyObject* /* unused */, PyObject* pyobject) { } //---------------------------------------------------------------------------- -static PyObject* BindObject(PyObject*, PyObject* args, PyObject* kwds) { +static PyObject* BindObject(PyObject* args, PyObject* kwds) { // From a long representing an address or a PyCapsule/CObject, bind to a // class. Py_ssize_t argc = PyTuple_GET_SIZE(args); @@ -1022,20 +1022,20 @@ static PyMethodDef gcpyrtMethods[] = { METH_VARARGS, (char*)"cppjit internal function"}, {(char*)"_set_cpp_lazy_lookup", (PyCFunction)SetCppLazyLookup, METH_VARARGS, (char*)"cppjit internal function"}, - {(char*)"_DestroyPyStrings", (PyCFunction)cpyrt::DestroyPyStrings, + {(char*)"_DestroyPyStrings", cpyrt::DestroyPyStrings, METH_NOARGS, (char*)"cppjit internal function"}, - {(char*)"addressof", (PyCFunction)addressof, METH_VARARGS | METH_KEYWORDS, + {(char*)"addressof", addressof, METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field as a value."}, - {(char*)"as_cobject", (PyCFunction)AsCObject, METH_VARARGS | METH_KEYWORDS, + {(char*)"as_cobject", AsCObject, METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a CObject."}, - {(char*)"as_capsule", (PyCFunction)AsCapsule, METH_VARARGS | METH_KEYWORDS, + {(char*)"as_capsule", AsCapsule, METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a PyCapsule."}, - {(char*)"as_ctypes", (PyCFunction)AsCTypes, METH_VARARGS | METH_KEYWORDS, + {(char*)"as_ctypes", AsCTypes, METH_VARARGS | METH_KEYWORDS, (char*)"Retrieve address of proxied object or field in a ctypes " "c_void_p."}, {(char*)"as_memoryview", (PyCFunction)AsMemoryView, METH_O, (char*)"Represent an array of objects as raw memory."}, - {(char*)"bind_object", (PyCFunction)BindObject, + {(char*)"bind_object", BindObject, METH_VARARGS | METH_KEYWORDS, (char*)"Create an object of given type, from given address."}, {(char*)"move", (PyCFunction)Move, METH_O, diff --git a/src/interop/cppjit_interop.h b/src/interop/cppjit_interop.h index ca7c07e..9787e56 100644 --- a/src/interop/cppjit_interop.h +++ b/src/interop/cppjit_interop.h @@ -271,8 +271,7 @@ std::string GetMethodArgName(TCppMethod_t, TCppIndex_t iarg); RPY_EXPORTED TCppType_t GetMethodArgType(TCppMethod_t, TCppIndex_t iarg); RPY_EXPORTED -TCppIndex_t CompareMethodArgType(TCppMethod_t, TCppIndex_t iarg, - const std::string& req_type); +TCppIndex_t CompareMethodArgType(TCppMethod_t); RPY_EXPORTED std::string GetMethodArgTypeAsString(TCppMethod_t method, TCppIndex_t iarg); RPY_EXPORTED diff --git a/src/interop/interop_wrapper.cxx b/src/interop/interop_wrapper.cxx index cce30fa..32a4a9f 100644 --- a/src/interop/interop_wrapper.cxx +++ b/src/interop/interop_wrapper.cxx @@ -829,6 +829,7 @@ static inline bool copy_args(Parameter* args, size_t nargs, void** vargs) { switch (args[i].fTypeCode) { case 'X': /* (void*)type& with free */ runRelease = true; + break; case 'V': /* (void*)type& */ vargs[i] = args[i].fValue.fVoidp; break; @@ -1254,8 +1255,7 @@ std::string interop::GetMethodArgDefault(TCppMethod_t method, } interop::TCppIndex_t -interop::CompareMethodArgType(TCppMethod_t /*method*/, TCppIndex_t iarg, - const std::string& req_type) { +interop::CompareMethodArgType(TCppMethod_t /*method*/) { // if (method) { // TFunction* f = m2f(method); // TMethodArg* arg = (TMethodArg diff --git a/test/Makefile b/test/Makefile index e07e775..6000dcd 100644 --- a/test/Makefile +++ b/test/Makefile @@ -26,7 +26,7 @@ cppflags= -std=c++17 -O3 -fPIC -I$(shell $(PYTHON) -c 'import sysconfig as sc; p PLATFORM := $(shell uname -s) ifeq ($(PLATFORM),Darwin) - cppflags+=-dynamiclib -single_module -undefined dynamic_lookup -Wno-delete-non-virtual-dtor + cppflags+=-dynamiclib -undefined dynamic_lookup -Wno-delete-non-virtual-dtor endif cpp/%Dict.so: cpp/%.cxx