473,549 Members | 2,723 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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

I am trying to pass a C++ object to Python function. This Python
function then calls another C++ function which then uses this C++
object to call methods of that object's class.

I tried something like this, but it did not work, gave core dump.

class myclass {
public:
myclass(){};
~myclass(){};
void printmyname() { printf("I am myclass, num=%d\n",num); };
};

main(){
myclass myobj

char funcbody[]=\
"def pyfunction(t167 ,classobj):\n\
onemorefunc(t16 7,\"NONAMe\")\n \
return 10\n\
\n\n";

// compile this Python function using PyRun_String & get its pointer
by PyObject_GetAtt rString.
// Later call it as below:
myclass myobj(23);
PyObject *pTuple = 0;
pTuple = PyTuple_New(2);
PyTuple_SetItem (pTuple,0,PyStr ing_FromString( "NAME")); // for t167
parameter
PyObject *inputarg = Py_BuildValue(" OO&",pTuple,myo bj); // for
classobj parameter

result = PyObject_CallOb ject(pPyEvalFun ction,inputarg) ;
}

How can I pass this class object to Python function?
Is it possible to set it in tuple using PyTuple_SetItem , because I may
have varying number of arguments for my Python functions & that's why
I can't use Py_BuildValue.
Jun 27 '08 #1
9 4978
grbgooglefan wrote:
I am trying to pass a C++ object to Python function. This Python
function then calls another C++ function which then uses this C++
object to call methods of that object's class.
You might consider using a C++-wrapper like SIP, Swig or Boost::Python to do
this.

If you don't like that, all I can think of would be to return the address of
the object as integer, and pass that around. Then in the appropriate
C++-call, cast that integer to the object. butt-ugly and -10 style-points
though.

Diez
Jun 27 '08 #2
En Mon, 21 Apr 2008 10:24:15 -0300, grbgooglefan <ga*********@gm ail.comescribió :
I am trying to pass a C++ object to Python function. This Python
function then calls another C++ function which then uses this C++
object to call methods of that object's class.

I tried something like this, but it did not work, gave core dump.
You can't pass any arbitrary C object to a Python function.
In this case you can use a PyCObject, a Python box around a void* pointer.
See http://docs.python.org/api/cObjects.html
// compile this Python function using PyRun_String & get its pointer
by PyObject_GetAtt rString.
// Later call it as below:
myclass myobj(23);
PyObject *pTuple = 0;
pTuple = PyTuple_New(2);
PyTuple_SetItem (pTuple,0,PyStr ing_FromString( "NAME")); // for t167
parameter
PyObject *inputarg = Py_BuildValue(" OO&",pTuple,myo bj); // for
classobj parameter

result = PyObject_CallOb ject(pPyEvalFun ction,inputarg) ;
}

How can I pass this class object to Python function?
Is it possible to set it in tuple using PyTuple_SetItem , because I may
have varying number of arguments for my Python functions & that's why
I can't use Py_BuildValue.
You have to check every call for errors, and pay attention to the reference counts!
The argument passing is wrong. You never set the second tuple element. An easier way is using PyObject_CallFu nctionObjArgs(f unction, arg1, arg2, NULL)

--
Gabriel Genellina

Jun 27 '08 #3
Gabriel Genellina wrote:
En Mon, 21 Apr 2008 10:24:15 -0300, grbgooglefan <ga*********@gm ail.com>
escribió:
>I am trying to pass a C++ object to Python function. This Python
function then calls another C++ function which then uses this C++
object to call methods of that object's class.

I tried something like this, but it did not work, gave core dump.

You can't pass any arbitrary C object to a Python function.
In this case you can use a PyCObject, a Python box around a void* pointer.
See http://docs.python.org/api/cObjects.html
Neat! Didn't know about that one.

Diez
Jun 27 '08 #4
On Apr 21, 10:17*pm, "Gabriel Genellina" <gagsl-...@yahoo.com.a r>
wrote:
En Mon, 21 Apr 2008 10:24:15 -0300, grbgooglefan <ganeshbo...@gm ail.comescribió :
I am trying to pass a C++ object to Python function. This Python
function then calls another C++ function which then uses this C++
object to call methods of that object's class.
I tried something like this, but it did not work, gave core dump.

You can't pass any arbitrary C object to a Python function.
In this case you can use a PyCObject, a Python box around a void* pointer.
Seehttp://docs.python.org/api/cObjects.html
Yup, I looked at http://www.python.org/doc/ext/using-cobjects.html
also. I could not find in this example where is CObject used or
converted back from Python to C.
Is there any tutorial which I can use for this?
Jun 27 '08 #5
En Mon, 21 Apr 2008 19:11:31 -0300, grbgooglefan <ga*********@gm ail.com>
escribió:
On Apr 21, 10:17*pm, "Gabriel Genellina" <gagsl-...@yahoo.com.a r>
wrote:
>En Mon, 21 Apr 2008 10:24:15 -0300, grbgooglefan
<ganeshbo...@g mail.comescribi ó:
I am trying to pass a C++ object to Python function. This Python
function then calls another C++ function which then uses this C++
object to call methods of that object's class.
I tried something like this, but it did not work, gave core dump.

You can't pass any arbitrary C object to a Python function.
In this case you can use a PyCObject, a Python box around a void*
pointer.
Seehttp://docs.python.org/api/cObjects.html

Yup, I looked at http://www.python.org/doc/ext/using-cobjects.html
also. I could not find in this example where is CObject used or
converted back from Python to C.
Is there any tutorial which I can use for this?
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_AsVoi dPtr:

void foo(PyObject *pyobj)
{
TOriginalType *porig;
porig = (TOriginalType *)PyCObject_AsV oidPtr(pyobj);
// do something with porig
}

--
Gabriel Genellina

Jun 27 '08 #6
En Mon, 21 Apr 2008 11:19:24 -0300, Diez B. Roggisch <de***@nospam.w eb.de>
escribió:
Gabriel Genellina wrote:
>You can't pass any arbitrary C object to a Python function.
In this case you can use a PyCObject, a Python box around a void*
pointer.
See http://docs.python.org/api/cObjects.html

Neat! Didn't know about that one.
I found it just by chance. The title alone in the API reference isn't very
descriptive...

--
Gabriel Genellina

Jun 27 '08 #7
On Apr 22, 7:54*am, "Gabriel Genellina" <gagsl-...@yahoo.com.a r>
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_AsVoi dPtr:

void foo(PyObject *pyobj)
{
* *TOriginalType *porig;
* *porig = (TOriginalType *)PyCObject_AsV oidPtr(pyobj);
* *// do something with porig
}
--
Gabriel Genellina- Hide quoted text -

- Show quoted text -
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*, intElements;
typedef hash_map<char*, Elements*,Strin gHash,eqstr>
PerExchGroupsEl ementsTable;
typedef struct capsule {
PerExchGroupsEl ementsTable* refgrps;
} *pcapsule;

// In pyinterface.cpp file:---
numvars = // value set depending on number of variables of that python
function
PyObject *pTuple = PyTuple_New(num vars);

// 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,Py Int_FromLong(or dvars[slot].nvalue));
break;
case(FLOAT_T):

PyTuple_SetItem (pTuple,nCtr,Py Float_FromDoubl e(ordvars[slot].fvalue));
break;
case(STRING_T):

PyTuple_SetItem (pTuple,nCtr,Py String_FromStri ng(ordvars[slot].cvalue));
break;
default:
printf("\nUnkno wn data type [%d] for %s\n",ndtyp,pru l-
>pVarLst[nCtr].var);
bUnknownDataTyp e = true;
break;
}
if(bUnknownData Type){
ret = -1;
break;
}
}

// Then set the C++ object as below:
if(ret == 0){
capsule grpob;
if(pGroups){
grpob.refgrps = pGroups; // pGroups is pointer to
PerExchGroupsEl ementsTable map & is global.
int ret = PyTuple_SetItem (pTuple,
(numvars-1),PyCObject_Fr omVoidPtr((void *)&grpob, NULL));
}
PyObject *pResult = PyObject_CallOb ject(pfunc,pTup le);
if(PyErr_Occurr ed()){
printf("error occured in PyObject_CallOb ject for %s\n",prul-
>pyobj.szPyRout eName);
PyErr_Print();
} else {
printf("Python function passed, use its result for other
purposes as designed\n");
}
Py_XDECREF(pRes ult);
Py_XDECREF(pTup le);
}

//---------- My Pythong module & functions in it -------------------
//PyObject* pfunc is a Python function which I compile dynamically &
add to my Python module as below:
// One of such dynamically compiled function is as below:
char pyfunction[]=\
"def TSE581(t22,t52, t1012,ob):
if(co1(ob,t22,\ "TSE_FUTURE_GRP \") and
like1(ob,t52,\" TSE_SECID_LST2\ ")):\n\
print \"result is pass\"\n\
return 1\n\
else:\n\
print \"result is fail\"\n\
return 0\n";

// function parameter "ob" in this function definition is the one
which Im passing as CObject.

PyObject *result = NULL;
result =
PyRun_String(py function,Py_fil e_input,_pPyDic tionary,_pPyDic tionary);
if(PyErr_Occurr ed() || result == NULL){
printf("Failed to compile function [%s]\n",func);
PyErr_Print();
return;
}
Py_XDECREF(resu lt);
result = NULL;
PyObject *ptr = PyObject_GetAtt rString(_pPyMod ule,fname);
if(PyErr_Occurr ed() || *ptr == NULL){
printf("PyObjec t_GetAttrString failed:%s",fnam e);
return;
}
if(!PyCallable_ Check(*ptr)){
printf("%s not a callable Python code\n",fname);
Py_XDECREF(*ptr );
*ptr = NULL;
return;
}

// I've created dynamically loadble Python module & multiple functions
similar to above gets added dynamically to this module.
// Module has functions "co1" & "like1" in module's .cpp file. These
functions then use CObject - the struct capsule & map pointer in it.
static PyObject* merorderrouter_ co1(PyObject* self, PyObject* args)
{
printf("Contain s function\n");
int ret=0;
char *arg1=NULL, *arg2=NULL;
PyObject* voidcap=NULL;
if(!PyArg_Parse Tuple(args, "Oss", &voidcap,&arg1, &arg2)){
printf("failed to get args\n");
if(PyErr_Occurr ed())
PyErr_Print();
return(PyInt_Fr omLong(ret));
}
printf("key=%s, grpname=[%s]\n",arg1,arg2 );
if(voidcap && PyCObject_Check (voidcap))
printf("valid Py-C-Object\n");
else
printf("NOT a valid Py-C-Object\n");
pcapsule pobj = (pcapsule)PyCOb ject_AsVoidPtr( voidcap);
if(pobj){
PerExchGroupsEl ementsTable grpmap = *pobj->refgrps;
if(grpmap.count (arg2)){
PerExchGroupsEl ementsTable::it erator grpmi =
grpmap.find(arg 2);
Elements grpelems = *(Elements*)grp mi->second;
Elements::itera tor ei = grpelems.find(a rg1);
if(ei != grpelems.end()) {
printf("has elm.\n");
ret=1;
} else {
printf("no elm.\n");
ret=0;
}
}
} else {
printf("pcapsul e object is null from PyCObject_AsVoi dPtr
\n");
if(PyErr_Occurr ed())
PyErr_Print();
}
printf("------- co returning.....\ n");
return PyInt_FromLong( ret);
}
//=============== =============== =============== ==========

What happens is that when Python function TSE581 gets called from my C
Program via PyObject_CallOb ject (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?
2) Am I missing to increase or decrease the reference count somewhere.
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.

If want to see my Python module & the CPP code using it, I can send
all my source code to you.
Please help.
Jun 27 '08 #8
En Fri, 02 May 2008 00:26:38 -0300, grbgooglefan <ga*********@gm ail.com>
escribió:
On Apr 22, 7:54*am, "Gabriel Genellina" <gagsl-...@yahoo.com.a r>
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_AsVoi dPtr:

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*, intElements;
typedef hash_map<char*, Elements*,Strin gHash,eqstr>
PerExchGroupsEl ementsTable;
typedef struct capsule {
PerExchGroupsEl ementsTable* refgrps;
} *pcapsule;

// In pyinterface.cpp file:---
numvars = // value set depending on number of variables of that python
function
PyObject *pTuple = PyTuple_New(num vars);

// 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,Py Int_FromLong(or dvars[slot].nvalue));
break;
case(FLOAT_T):
PyTuple_SetItem (pTuple,nCtr,Py Float_FromDoubl e(ordvars[slot].fvalue));
break;
case(STRING_T):
PyTuple_SetItem (pTuple,nCtr,Py String_FromStri ng(ordvars[slot].cvalue));
break;
default:
printf("\nUnkno wn data type [%d] for %s\n",ndtyp,pru l-
>pVarLst[nCtr].var);
bUnknownDataTyp e = true;
break;
}
if(bUnknownData Type){
ret = -1;
break;
}
}

// Then set the C++ object as below:
if(ret == 0){
capsule grpob;
if(pGroups){
grpob.refgrps = pGroups; // pGroups is pointer to
PerExchGroupsEl ementsTable map & is global.
int ret = PyTuple_SetItem (pTuple,
(numvars-1),PyCObject_Fr omVoidPtr((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_GetAtt rString(_pPyMod ule,fname);
if(PyErr_Occurr ed() || *ptr == NULL){
printf("PyObjec t_GetAttrString failed:%s",fnam e);
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_CallOb ject (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

Jun 27 '08 #9
Yes, that worked. I "protected" the variable which I did not want to
get freed. I incremented reference for that variable & it started
working.

Thanks for all your guidance.

On May 3, 5:23*am, "Gabriel Genellina" <gagsl-...@yahoo.com.a rwrote:
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- Hide quoted text -

- Show quoted text -
Jun 27 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
2369
by: python | last post by:
When I pass a function as an arg, like for map(...), how do I pass args to use for that function? If I have a function like this: def pretty_format(f, fmt='%0.3f'): return fmt % f I want to use it with map() like this:
46
3466
by: J.R. | last post by:
Hi folks, The python can only support passing value in function call (right?), I'm wondering how to effectively pass a large parameter, such as a large list or dictionary? It could achieved by pointer in C++, is there such way in Python? Thansk in advance. J.R.
3
3037
by: Robert | last post by:
Python doesn't know the class of a method when container not direct class attribute: >>> class X: .... def f():pass .... g=f .... l= .... >>> X.g <unbound method X.f>
10
2049
by: Doug Jordan | last post by:
I am fairly new to Python. This should be an easy answer but I cannot get this to work. The code is listed below. I know how to do this in C, Fortran, and VB but it doesn't seem to work the same way here. I would appreciate any help. #try this to pass a list to a function and have the function return #a variable #this works list= def...
2
2135
by: Aaron | last post by:
I have a data sructure setup and I populate it in a loop like so: y=0 while X: DS.name = "ASDF" DS.ID = 1234 list = DS; y = y + 1
10
13619
by: Robert Dailey | last post by:
Hi, I noticed in Python all function parameters seem to be passed by reference. This means that when I modify the value of a variable of a function, the value of the variable externally from the function is also modified. Sometimes I wish to work with "copies", in that when I pass in an integer variable into a function, I want the...
15
1369
by: J. Peng | last post by:
Hello, I saw this statement in Core Python Programming book, All arguments of function calls are made by reference, meaning that any changes to these parameters within the function affect the original objects in the calling function. Does this mean there is not pass-values calling to a function in
12
3000
by: Bryan Parkoff | last post by:
I write my large project in C++ source code. My C++ source code contains approximate four thousand small functions. Most of them are inline. I define variables and functions in the global scope. The global variables and global functions are hidden to prevent from accessing by the programmers. All global functions share global variables....
12
11031
by: raylopez99 | last post by:
Keywords: scope resolution, passing classes between parent and child forms, parameter constructor method, normal constructor, default constructor, forward reference, sharing classes between forms. Here is a newbie mistake that I found myself doing (as a newbie), and that even a master programmer, the guru of this forum, Jon Skeet, missed!...
0
7520
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7450
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7957
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7470
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7809
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
5088
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3500
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
1941
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
763
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.