how to pass C++ object to another C++ function via Python function

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Fri May 2 17:23:40 EDT 2008


En Fri, 02 May 2008 00:26:38 -0300, grbgooglefan <ganeshborse at gmail.com>  
escribió:

> On Apr 22, 7:54 am, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
> wrote:
>>
>> If you have a C function that receives a PyCObject, just include the  
>> relevant headers (cobject.h) and you can retrieve the original pointer  
>> using PyCObject_AsVoidPtr:
>>
>
> This works. But only once, means if I try to use this object second
> time in Python function it causes crash.
>
> What I am doing in my program is that I am putting STL map in a
> structure & passing that structure as object to a Python function
> alongwith other agurments of that Python function. This briefly as
> below:
>
> // In pyinterface.h file:---
> typedef hash_map<char*,int> Elements;
> typedef hash_map<char*,Elements*,StringHash,eqstr>
> PerExchGroupsElementsTable;
> typedef struct capsule {
>         PerExchGroupsElementsTable* refgrps;
> } *pcapsule;
>
> // In pyinterface.cpp file:---
> numvars = // value set depending on number of variables of that python
> function
> PyObject *pTuple = PyTuple_New(numvars);
>
> // Set variables as below:
> for(nCtr = 0; nCtr < numvars; nCtr++){
>      slot = prul->pVarLst[nCtr].slot;
>      ndtyp = ordvars[slot].dtype;
>      switch(ndtyp){
>        case(INT_T):
> PyTuple_SetItem(pTuple,nCtr,PyInt_FromLong(ordvars[slot].nvalue));
>            break;
>        case(FLOAT_T):
> PyTuple_SetItem(pTuple,nCtr,PyFloat_FromDouble(ordvars[slot].fvalue));
>            break;
>        case(STRING_T):
> PyTuple_SetItem(pTuple,nCtr,PyString_FromString(ordvars[slot].cvalue));
>            break;
>        default:
>            printf("\nUnknown data type [%d] for %s\n",ndtyp,prul-
>> pVarLst[nCtr].var);
>            bUnknownDataType = true;
>            break;
>      }
>      if(bUnknownDataType){
>         ret = -1;
>         break;
>      }
> }
>
> // Then set the C++ object as below:
> if(ret == 0){
>     capsule grpob;
>     if(pGroups){
>       grpob.refgrps = pGroups; // pGroups is pointer to
> PerExchGroupsElementsTable map & is global.
>       int ret = PyTuple_SetItem(pTuple,
> (numvars-1),PyCObject_FromVoidPtr((void *)&grpob, NULL));
>     }

This look suspicious - what if !pGroups? You can't leave a tuple item  
uninitialized - if you create a tuple with PyTuple_New(3), then you have  
to fill the 3 items.
And beware of that local variable grpob - you're using a pointer to it,  
and it won't be valid when execution goes out of this block. You must  
ensure that nobody stores a reference to it.
And you should decref the tuple even if this block isn't executed.

>     PyObject *ptr = PyObject_GetAttrString(_pPyModule,fname);
>     if(PyErr_Occurred() || *ptr == NULL){
>         printf("PyObject_GetAttrString failed:%s",fname);
>         return;
>     }
>     if(!PyCallable_Check(*ptr)){
>        printf("%s not a callable Python code\n",fname);
>        Py_XDECREF(*ptr);
>        *ptr = NULL;
>        return;
>     }

All those *ptr should be ptr (the compiler should issue a lot of warnings,  
I presume?)

> What happens is that when Python function TSE581 gets called from my C
> Program via PyObject_CallObject (as shown at top of this post), co1
> function works fine & can access the map pointer properly.
> But when next function like1 gets called, crash happens.
>
> My queries are & things on which I need help are:
> 1) Is there anything wrong I am doing when I am passing the C-Object
> from my C++ code->Python -> C++ code again?

I see nothing obviously wrong, except the above notes. If you get warnings  
 from the C++ compiler, try to fix all of them.

> 2) Am I missing to increase or decrease the reference count somewhere.

In case of error you exit early but without releasing some existing  
objects. (Sometimes a goto statement *is* the right thing to do)

> 3) I dont want map pointer to be ever freed because it is Process
> level data structure & requried at every execution of these Python
> functions. How do I avoid its cleanup when it gets passed to Python &
> Python cleans up those objects.

Python will do nothing with the pointer inside a PyCObject - unless you  
want to, and pass a cleanup function as the second argument to the  
PyCObject constructor.

-- 
Gabriel Genellina




More information about the Python-list mailing list