C Ext Questions

D

djw

Hello, I have a couple of questions about some code in a C extension module.
First, how would I convert a Python string return value from a call to
PyObject_CallFunction into a C void * buffer? Second, do I need to call
Py_XINCREF() on my callback function? (Sorry, the code is kind of
preliminary and rough)

Thanks,

Don


ext.c
-----

PyObject * callback = NULL;

PyObject * set_callback( PyObject * self, PyObject * args )
{
if( !PyArg_ParseTuple( args, "O", &callback ) )
{
return Py_BuildValue( "i", 1 );
}

if( !PyCallable_Check( callback ))
{
return Py_BuildValue( "i", 2 );
}

Py_XINCREF( callback );
}

int call_callback( int param1, int param2, void * buf, int size )
{
PyObject * result;

if( callback )
{
result = PyObject_CallFunction( callback, "ii", param1, param2 );
// Need to convert return Python string into buf....????
}
}

PyObject * do_something( PyObject * self, PyObject * args )
{
char buf[512];
call_callback( 1, 1, (void *)&buf, sizeof(buf) );
// buf should now contain: "This is the callback return string"
}

....


wrapper.py
----------

import ext

def f1():
return "This is the callback return string"

ext.set_callback( f1 )
ext.do_something()

....
 
M

Michael Hudson

djw said:
Hello, I have a couple of questions about some code in a C extension module.
First, how would I convert a Python string return value from a call to
PyObject_CallFunction into a C void * buffer?

PyString_AsString(). Do check for NULL return in case the the object
isn't a string...
Second, do I need to call Py_XINCREF() on my callback function?

Yes, though the code as posted would be fine with Py_INCREF().

Have you read the fine (well, ish) manuals on this sort of thing?

Cheers,
mwh
 
P

Pete Shinners

PyObject * set_callback( PyObject * self, PyObject * args )
{
if( !PyArg_ParseTuple( args, "O", &callback ) )
{
return Py_BuildValue( "i", 1 );
}
if( !PyCallable_Check( callback ))
{
return Py_BuildValue( "i", 2 );
}
Py_XINCREF( callback );
}

You are increasing the refcount here, but before you assign a new
callback, you will want to decrease the reference to the old callback.
Your other problem is that if PyArg_ParseTuple fails, it is raising an
exception. Your function _must_ return NULL or clear the exception.
Better to return NULL and let the exception get raised.

int call_callback( int param1, int param2, void * buf, int size )
{
PyObject * result;

if( callback )
{
result = PyObject_CallFunction( callback, "ii", param1, param2 );
// Need to convert return Python string into buf....????
}
}

You will need to get a char* pointer and copy that into your buffer.
char * str;
str = PyString_AsString(result);
if(!str)
{
Py_XDECREF(result);
return NULL;
}
strncpy((char*)buf, str, size-1);
((char*)buf)[size-1] = 0;
Py_DECREF(result);
return 1;


One last warning, if your program involves multiple threads, make sure
the Python callback only gets called from the primary thread. You'll
have a lot of "non-beginner" work to do to safely call the Python
callback from any thread. Anyways, this is probably not an issue.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top