PyObject_CallObject: difference between functions and class methods

M

mauro

Hi all!

I am trying to call within a C extension a Python function provided as
an argument by the user with: PyObject_Call(). The C extension should
work also if the user supplies a class method, but in this case I am
getting an error. Do I need to explicitly pass 'self' as an argument
to PyObject_Call()? If so, how can I do that?

Now, I am using:

if ((tmp_args = PyTuple_New(1)) == NULL)
PyErr_SetString( PyExc_ReferenceError, "attempt to access a null-
pointer" );
PyTuple_SetItem(tmp_args, 0, paramlist);

to create the tuple required by PyObject_Call(), but I have no idea on
how to add a reference to 'self'.

Here is what I would like to obtain:

##
import mymodule

def myfunc(x):
# Do something
return [z]

class MyClass:
def mymethod(self, x):
# Do something
return z
def runme(self):
mymodule.main(myfunc) # This will work
mymodule.main(self.mymethod) # This will not work (Segmentation
fault)

x = MyClass()
x.runme()
##

Thanks in advance.

Mauro
 
H

Hrvoje Niksic

[ Note that there is now a mailing list dedicated to the C API:
http://mail.python.org/mailman/listinfo/capi-sig ]

mauro said:
I am trying to call within a C extension a Python function provided as
an argument by the user with: PyObject_Call(). The C extension should
work also if the user supplies a class method, but in this case I am
getting an error. Do I need to explicitly pass 'self' as an argument
to PyObject_Call()?

You don't. The reference to self will be added automatically when
invoking the function you receive as object.method.
if ((tmp_args = PyTuple_New(1)) == NULL)
PyErr_SetString( PyExc_ReferenceError, "attempt to access a null-
pointer" );
PyTuple_SetItem(tmp_args, 0, paramlist);

Maybe you are mismanaging the reference count -- PyTuple_SetItem
steals the refcount of its argument. Anyway, why not use
PyObject_CallFunction or PyObject_CallFunctionObjArgs? For example:

PyObject *
mymodule_main(PyObject *ignored, PyObject *func)
{
PyObject *result, *my_param;
/* ... do something, e.g. create my_param ... */

/* call func */
result = PyObject_CallFunction(received_func, "O", my_param);
Py_DECREF(my_param); /* assuming you no longer need it */
if (!result)
return NULL;

/* ... do something with result ... */

Py_DECREF(result);
Py_INCREF(Py_None);
return Py_None; /* or whatever */
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top