Now, we'll convert this example, that defines a Python function, then calls it with some arguments.
Setting up the function
First, we need a method to compile Python code.
Object*
Object::compileString( const char* pCodeBuf )
{
// compile the string
PyObject* pCodeObj = Py_CompileString( pCodeBuf , "" , Py_file_input ) ;
if ( pCodeObj == NULL )
Exception::translateException() ;
return new Object( pCodeObj , true ) ;
}
We call Py_CompileString() to compile the code, throw an exception if something went wrong, then return a new Object that wraps the PyObject Python returns us. When the caller has finished using it and deletes it, its reference count will be decremented and it will eventually get cleaned up[1]Assuming that no-one else has taken a reference to it..
Next we need to load the code into a module.
Object*
Object::execCodeModule( const char* pModuleName , Object& codeObj )
{
// execute the code module
PyObject* pModuleObj = PyImport_ExecCodeModule( (char*)pModuleName , codeObj.pPyObject() ) ;
if ( pModuleObj == NULL )
Exception::translateException() ;
return new Object( pModuleObj , true ) ;
}
Pretty similar, except this time we return an Object that represents the module.
Finally, we want to locate our function in the module.
Object*
Object::getAttr( const char* pAttrName ) const
{
// return the specified attribute
PyObject* pAttrObj = PyObject_GetAttrString( pPyObject() , pAttrName ) ;
if ( pAttrObj == NULL )
Exception::translateException() ;
return new Object( pAttrObj , true ) ;
}
This is a general method that will search any object for a specific attribute, returning an Object representing that attribute (if it was found).
The example code to set up the function now looks like this.
// define our test function
stringstream buf ;
buf << "def add( n1 , n2 ) :" << endl
<< " return n1+n2" << endl ;
auto_ptr<Object> pCompiledFn( Object::compileString( buf.str().c_str() ) ) ;
auto_ptr<Object> pModule( Object::execCodeModule( "test" , *pCompiledFn ) ) ;
auto_ptr<Object> pAddFn( pModule->getAttr( "add" ) ) ;
Preparing the function parameters
To set up the parameters to be passed into the function, we need to be able to create tuples and dictionaries.
Object* Object::newTuple( size_t n ) { PyObject* p=PyTuple_New(n) ; return new Object(p,true) ; }
Object* Object::newDict() { PyObject* p=PyDict_New() ; return new Object(p,true) ; }
We also need to be able to set items in a tuple.
void
Object::setTupleItem( size_t pos , Object& obj )
{
// set the tuple item
int rc = PyTuple_SetItem( pPyObject() , pos , obj.pPyObject() ) ;
if ( rc != 0 )
Exception::translateException() ;
// NOTE: The tuple takes ownership of the object, so it doesn't need to decref itself.
obj.mDecRef = false ;
}
Note how we tell the Object being added that it no longer needs to decrement its reference count when it gets destroyed, because the tuple will take care of it.
The example code to set up the function parameters now looks like this[2]Note that this code uses a helper function that creates an Object from an int.:
// prepare the function parameters auto_ptr<Object> pPosArgs( Object::newTuple( 2 ) ) ; pPosArgs->setTupleItem( 0 , Object(-2) ) ; pPosArgs->setTupleItem( 1 , Object(15) ) ;
Calling the function
Now, all we have to do is call the function.
Object*
Object::callObj( Object& args , Object& kywdArgs )
{
// call the object
PyObject* pResultObj = PyObject_Call( pPyObject() , args.pPyObject() , kywdArgs.pPyObject() ) ;
if ( pResultObj == NULL )
Exception::translateException() ;
return new Object( pResultObj , true ) ;
}
// call the function auto_ptr<Object> pKywdArgs( Object::newDict() ) ; auto_ptr<Object> pResult( pAddFn->callObj( *pPosArgs , *pKywdArgs ) ) ;
callObj() returns an Object that represent the value returned by the function, so we need a method to repr a Python object, so we can print it out.
string
Object::reprVal() const
{
// return the "repr" value for the Python object
// NOTE: We have to return a std::string since PyString_AsString() returns
// a char* for the "repr" object, which will be destroyed when we return.
Object repr( PyObject_Repr(mpPyObject) , true ) ;
return PyString_AsString( repr.pPyObject() ) ;
}
cout << "The answer: " << pResult->reprVal() << endl ;
Download the source code here.










I am a 
