[C++-sig] boost.python: when does python call c++ destructors?

Sebastian Walter walter at mathematik.hu-berlin.de
Fri Feb 29 15:11:08 CET 2008


Ok, I figured out what I have been missing. Actually it are two things

1) C++ automatically defines a standard copy constructor when it is not 
manually defined.

2)In Python the expression  "c = a*b" first computes a*b where a temporary 
object tmp is created. But instead of using this tmp object and give it the 
name c, Python does the following:
The copy constructor with tmp as argument is called and this new copy 
is "given the name" c.


So, since the standard copy constructor does not increase global_int nor does 
it cout the "called constructor" string, this led to the unexpected behavior 
that I couldn't explain.

If I add and wrap the copy constructor:
asdf::asdf(const asdf& a) {
	loc = global_int;
	cout << "called copy constructor with loc:\t" << loc << endl;
	global_int++;
}

i get the correct result.
wronski(walter):~/workspace/code_tests/boost_python> ./test.py
called constructor with loc:    0
called constructor with loc:    1
called operator* with locs:     (0,1)
called constructor with loc:    2
called copy constructor with loc:       3
called destructor with loc:     2
called operator* with locs:     (0,3)
called constructor with loc:    3
called copy constructor with loc:       4
called destructor with loc:     3
end
called destructor with loc:     0
called destructor with loc:     3
called destructor with loc:     1
called destructor with loc:     4








On Thursday, 28. February 2008 13:26:24 Sebastian Walter wrote:
> Hello,
> I have compiled a python module with boost.python that exposes the
> functionality of a c++ class that has a constructor and destructor and an
> overloaded operator*. The complete c++ code and wrapper can be found at the
> bottom of this email:
>
> But at first the python script that gives me headaches:
>
> /* test.py */
> /*-----------*/
> #!/usr/bin/env python
> import myclass
>
> a = myclass.asdf()
> b = myclass.asdf()
>
> c = a * b
> d = a * c
>
> /* output of test.py */
> /*-----------------------*/
> wronski(walter):~/workspace/code_tests/boost_python> ./test.py
> called constructor with loc:    0
> called constructor with loc:    1
> called operator* with locs:     (0,1)
> called constructor with loc:    2
> called destructor with loc:     2		?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
> called operator* with locs:     (0,2)
> called constructor with loc:    2
> called destructor with loc:     2
> called destructor with loc:     0
> called destructor with loc:     2
> called destructor with loc:     1
> called destructor with loc:     2
>
> The problem that I don't understand:
> a*b calls the constructor of a temporary object that is assigned loc=2
> and then directly after that the destructor is called! ...?
> I expected the new temporary object to get assigned to the name c!
>
> What bugs me even more is that there are 4 constructor calls but 6!!
> destructor calls! How can this happen?
>
> Is there something im overlooking? Is this intended behavior of
> Python/Boost.Python ?
> How could I avoid it?
>
>
> thanks in advance,
>
> Sebastian Walter
>
>
>
>
> The corresponding boost.python wrapper and c++ code:
>
> /* mainclass.hpp */
> /*----------------------*/
> #ifndef MAINCLASS_HPP
> #define MAINCLASS_HPP
>
> #include <iostream>
> #include <vector>
> using namespace std;
>
> class asdf{
> public:
> 	int loc;
> 	asdf();
> 	~asdf();
> 	friend const asdf operator*(const asdf &lhs, const asdf &rhs);
> };
> #endif
>
> /* mainclass.cpp */
> /*----------------------*/
> #include "mainclass.hpp"
>
> int global_int=0;
>
> asdf::asdf(){
> 	loc = global_int;
> 	cout<<"called constructor with loc:\t"<<loc<<endl;
> 	global_int++;
> }
>
> asdf::~asdf(){
> 	cout<<"called destructor with loc:\t"<<loc<<endl;
> 	global_int--;
> }
>
> const asdf operator*(const asdf &lhs, const asdf &rhs){
> 	cout<<"called operator* with
> locs:\t"<<"("<<lhs.loc<<","<<rhs.loc<<")"<<endl; return asdf();
> }
>
>
> /* wrapper.cpp */
> /*------------------*/
> #include "boost/python.hpp"
> #include "mainclass.hpp"
>
> BOOST_PYTHON_MODULE(myclass)
> {
> 	using namespace boost::python;
> 	class_<asdf>("asdf")
> 		.def(self * self)
> 	;
> }
>
>
>
>
>
>
> _______________________________________________
> C++-sig mailing list
> C++-sig at python.org
> http://mail.python.org/mailman/listinfo/c++-sig





More information about the Cplusplus-sig mailing list