Python calling C++ issues
Hi All, We are exploring the possibility of using Python with conjunction with C++. I recently posted the "Beginner Question" and would like to thank all of you for the great discussion and support we have received. We have managed to make great progress however we run into couple of very strange problems which I would like to bring up here and share them with the group. Any help in solving these issues will be highly appreciated and beneficiary for all. We also think that the attached example could be good starting point for beginners to understand the concept of calling C++ objects from Python. The example contains a simple C++ class with two data members and we have a simple python script which uses the class. The two problems are: 1. The value of the first data member in the class is ok in the constructor, but in all the rest of the member functions it added 2 to the first data member. 2. When we call the destructor, It is executing the destructor, but we get "Segmentation fault" after it finished to execute the python script that calls the functions that call c++ functions. Here is general information on: 1. We use Linux version 6.1 from redhat. 2. We use gcc version egcs-2.91.66 from redhat. 3. we use Python version 1.5.2 compiled with same gcc from redhat. 4. The class files are: spam.cpp and spam.h . 5. The files that include the c functions that wrap the class functions are : c_spam.cpp and c_spam.h . 6. The file that has the module extension is : ext_spam.cpp. 7. The file that includes the Python script that call the c++ is run. We suspect that the problems might be one or combination of the following issues: 2. Makefile bug (C++ flags and/or shared lib flags are missing). 3. Incompatibility between the way python was built and the version of GCC/C++ we use for the example. Thanks a lot in advance for your cooperation , Cheers, Ephi.
The problem is that Python thinks it is giving you an "Object *", but you are passing a "Spam *". For the same object, an "Object *" is off by the size of the virtual function pointer - an "Object *" doesnt have a vfptr, but a "Spam *" does. Change your code to: static PyObject* ext_Spam_Display(PyObject* self, PyObject* args) { Object *obSpam; if (!PyArg_ParseTuple(args, "O", &obSpam)) return NULL; Spam* spam = (Spam *)obSpam; Spam_Display(spam); return Py_BuildValue(""); } Check in the debugger - the "Object *" and "Spam *" will be different, even though they are the same object! Mark. -----Original Message----- From: c++-sig-admin@python.org [mailto:c++-sig-admin@python.org]On Behalf Of Ephi Dror Sent: Tuesday, 23 November 1999 5:50 To: c++-sig@python.org Subject: [C++-SIG] Python calling C++ issues Hi All, We are exploring the possibility of using Python with conjunction with C++. I recently posted the "Beginner Question" and would like to thank all of you for the great discussion and support we have received. We have managed to make great progress however we run into couple of very strange problems which I would like to bring up here and share them with the group. Any help in solving these issues will be highly appreciated and beneficiary for all. We also think that the attached example could be good starting point for beginners to understand the concept of calling C++ objects from Python. The example contains a simple C++ class with two data members and we have a simple python script which uses the class. The two problems are: 1. The value of the first data member in the class is ok in the constructor, but in all the rest of the member functions it added 2 to the first data member. 2. When we call the destructor, It is executing the destructor, but we get "Segmentation fault" after it finished to execute the python script that calls the functions that call c++ functions. Here is general information on: 1. We use Linux version 6.1 from redhat. 2. We use gcc version egcs-2.91.66 from redhat. 3. we use Python version 1.5.2 compiled with same gcc from redhat. 4. The class files are: spam.cpp and spam.h . 5. The files that include the c functions that wrap the class functions are : c_spam.cpp and c_spam.h . 6. The file that has the module extension is : ext_spam.cpp. 7. The file that includes the Python script that call the c++ is run. We suspect that the problems might be one or combination of the following issues: 2. Makefile bug (C++ flags and/or shared lib flags are missing). 3. Incompatibility between the way python was built and the version of GCC/C++ we use for the example. Thanks a lot in advance for your cooperation , Cheers, Ephi.
Hi Mark, Thanks a lot for your great help. Unfortunately, we don't seems to understand what do you mean by "Object". Is it something we need to define or is it already defined in a h file that we forgot to include. We use Linux/gcc environment. Also, in our sample, we did not use virtual function Below, for all of us we are using the WEB to look at the SIG C++ posting , please find the project files. Thanks, Ephi. ======================================================================== // c_spam.cpp #include "spam.h" extern "C" Spam* new_Spam(int a, int b) { Spam* spam = new Spam(a, b); return spam; } extern "C" void Spam_Display(Spam* spam) { spam->Display(); } extern "C" void delete_Spam(Spam* spam) { delete spam; } ======================================================================== // c_spam.h #include "spam.h" extern "C" Spam* new_Spam(int a, int b); extern "C" void Spam_Display(Spam* spam); extern "C" void delete_Spam(Spam* spam); ======================================================================== // ext_spam.cpp // spam extension module. #include "Python.h" #include "c_spam.h" static PyObject* ext_new_Spam(PyObject* self, PyObject* args) { int a, b; if (!PyArg_ParseTuple(args, "ii", &a, &b)) return NULL; Spam* spam = new_Spam(a, b); return Py_BuildValue("O", spam); } static PyObject* ext_Spam_Display(PyObject* self, PyObject* args) { Spam* spam; if (!PyArg_ParseTuple(args, "O", &spam)) return NULL; Spam_Display(spam); return Py_BuildValue(""); } static PyObject* ext_delete_Spam(PyObject* self, PyObject* args) { Spam* spam; if (!PyArg_ParseTuple(args, "O", &spam)) return NULL; delete_Spam(spam); return Py_BuildValue(""); } // "method table" static PyMethodDef c_spamMethods[] = { {"new_Spam", ext_new_Spam, 1}, {"Spam_Display", ext_Spam_Display, 1}, {"delete_Spam", ext_delete_Spam, 1}, {NULL,NULL} }; file://Initialization function that registers new methods with Python interpreter. extern "C" void initc_spam() { PyObject *m; m= Py_InitModule("c_spam", c_spamMethods); } ======================================================================== #makefile PPFLAGS = -fpic LFLAGS = CPP = g++ INCLUDE = /usr/include/python1.5 SOURCES = spam.cpp c_spam.cpp ext_spam.cpp OBJECTS = spam.o c_spam.o ext_spam.o TARGET = c_spammodule.so ####### Implicit rules .SUFFIXES: .cpp .cpp.o: $(CPP) $(CPPFLAGS) -c -I$(INCLUDE) $< ####### Build rules all: $(TARGET) $(TARGET): $(OBJECTS) $(CPP) -shared $(OBJECTS) -o $(TARGET) showfiles: @echo $(SOURCES) makefile clean: rm -f *.o rm -f $(TARGET) rm -f tags rm -f core ======================================================================== run: #!/usr/bin/python import c_spam myspam=c_spam.new_Spam(8, 5) c_spam.Spam_Display(myspam) c_spam.delete_Spam(myspam) print "python end" ======================================================================== // spam.cpp #include <iostream> #include "spam.h" Spam::Spam(int a, int b) : m_a(a), m_b(b) { cout << endl; cout << "In Spam::Spam, "; cout << "m_a = " << m_a << " m_b = " << m_b << endl; } void Spam::Display() { cout << "In Spam::Display, "; cout << "m_a = " << m_a << " m_b = " << m_b << endl; } Spam::~Spam() { cout << "In Spam::~Spam, "; cout << "m_a = " << m_a << " m_b = " << m_b << endl; } ======================================================================== // spam.h class Spam { public: Spam(int a, int b); void Display(); ~Spam(); private: int m_a; int m_b; }; ========================================================================
Unfortunately, we don't seems to understand what do you mean by "Object". Is it something we need to define or is it already defined in a h file that we forgot to include. We use Linux/gcc environment.
Sorry - I meant "PyObject"
Also, in our sample, we did not use virtual function
Hmmm - OK - my advice could well be wrong. Unless your C compiler always adds a vfptr. I have seen this problem (when using virtuals) before and the symptoms sound almost identical. Try the code snippet I posted, and see if the debugger does show the "PyObject *" and the "Spam *" as different values, even though they are pointing to the same object. Otherwise Im afraid I have no idea... Mark.
participants (2)
-
Ephi Dror -
Mark Hammond