Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble destructor,call python's object with pointer in boost.python

when I call python's function with pointer as an argument in boost.python, there are some troubles in destructor. The following is a sample code

c++

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <string>
#include <iostream>
using namespace boost::python;

class A {
public:
    A() {
        std::cout<< "A start"<<std::endl;
    }
    ~A() {std::cout<< "A end" <<std::endl;}
}
class B {
public:
    B() { aa=new A; }
    ~B() { delete aa; }
    void run(object ct) {
        _obj=ct();              //creat a python object
        _obj.attr("fun1")(aa);  //call a function named "fun1" with a pointer arg
        _obj.attr("fun2")(aa);  //call a function named "fun2" with a pointer arg 
    }
    A *aa;
    object _obj;
}

BOOST_PYTHON_MODULE(ctopy)
{
    class_<A> ("A",init<>())
    ;
    class_<b> ("B",init<>())
    .def("run",&B::run)
    ;
}

python:

import ctopy
class tc:
    def fun1(self,tt):
        print "fun1"
    def fun2(self,tt):
        print "fun2"
bb=ctopy.D()
bb.run(tc)

this result:

A start
fun1
A end
fun2
A end
A end

note:

The "A end" has been printed three.I try it in "valgrind",there are some errors.I just want to run the destructor once.How to do?

like image 500
simon Avatar asked Feb 04 '26 03:02

simon


1 Answers

To understand what's really happening, you're missing a copy-constructor:

B()
  A()
B::run()
  A(a)     <- copy construct A to pass by value
    fun1() <- arg passed by value
  ~A()     <- delete copy
  A(a)     <- copy construct A to pass by value
    fun2() <- arg passed by value
  ~A()     <- delete copy
~B()
  ~A()

In your example, aa is passed by value, that's where the copies come from. It does not matter if aa is a pointer or not, boost will convert it to an object that is passed to your python methods.

If you want to avoid additional copies of A you can pass aa by reference rather than by value:

_obj.attr("fun1")(boost::ref(aa));
_obj.attr("fun2")(boost::ref(aa));

Which will result in:

B()
  A()    <- constructed once
B::run()
  fun1() <- arg passed by reference
  fun2() <- arg passed by reference
~B()
  ~A()   <- destroyed once

See Calling Python Functions and Methods for more info.

like image 120
Anonymous Coward Avatar answered Feb 06 '26 17:02

Anonymous Coward



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!