Hrvoje Nikšić wrote: > On Wed, 2007-06-20 at 00:21 +1000, Campbell Barton wrote: >> I want to add my own call's before and after PyLists standard functions >> but have a proplem with functons that use keywords and have no API >> equivalent. >> For example, I cant use the API's PyList_Sort because that dosnt support >> keywords like... >> >> ls.sort(key=lambda a: a.foo)) >> >> And the Problem with PyObject_CallMethod is that it dosnt accept keywords. > > Note that you can always simply call PyObject_Call on the bound method > object retrieved using PyObject_GetAttrString. The hardest part is > usually constructing the keywords dictionary, a job best left to > Py_BuildValue and friends. When I need that kind of thing in more than > one place, I end up with a utility function like this one: > > /* Equivalent to PyObject_CallMethod but accepts keyword args. The > format... arguments should produce a dictionary that will be passed > as keyword arguments to obj.method. > > Usage example: > PyObject *res = call_method(lst, "sort", "{s:O}", "key", keyfun)); > */ > > PyObject * > call_method(PyObject *obj, const char *methname, char *format, ...) > { > va_list va; > PyObject *meth = NULL, *args = NULL, *kwds = NULL, *ret = NULL; > > args = PyTuple_New(0); > if (!args) > goto out; > meth = PyObject_GetAttrString(obj, methname); > if (!meth) > goto out; > > va_start(va, format); > kwds = Py_VaBuildValue(format, va); > va_end(va); > if (!kwds) > goto out; > > ret = PyObject_Call(meth, args, kwds); > out: > Py_XDECREF(meth); > Py_XDECREF(args); > Py_XDECREF(kwds); > return ret; > } > > It would be nice for the Python C API to support a more convenient way > of calling objects and methods with keyword arguments.
Thanks for the hint, I ended up using PyObject_Call. This seems to work, EXPP_PyTuple_New_Prepend - is a utility function that returns a new tuple with self at the start (needed so args starts with self) I dont think I can use PyObject_GetAttrString because the subtype would return a reference to this function - rather then the lists original function, Id need an instance of a list and dont have one at that point. ______________________ static PyObject * MaterialList_sort(BPy_MaterialList *self, PyObject *args, PyObject *keywds ) { PyObject *ret; PyObject *newargs = EXPP_PyTuple_New_Prepend(args, (PyObject *)self); sync_list_from_materials__internal(self); # makes sure the list matches blenders materials ret = PyObject_Call(PyDict_GetItemString(PyList_Type.tp_dict, "sort"), newargs, keywds); Py_DECREF(newargs); if (ret) sync_materials_from_list__internal(self); # makes blenders materials match the lists return ret; } _____________________ Later on Ill probably avoid using PyDict_GetItemString on PyList_Type.tp_dict all the time since the methods for lists does not change during python running. - Can probably be assigned to a constant. -- Campbell J Barton (ideasman42) _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com