Welcome, guest | Sign In | My Account | Store | Cart

Managing ref-counting is a complex and error prone business. If you choose C++ to extend or embed Python, you can simply use a modification on std::auto_ptr. Instead of calling delete on the managed pointer, it will decref it.

So now you can do:

auto_py str = PyStr_FromString("Hello World!");

and forget about having to decref it altogether! Just like auto_ptr you can get the PyObject * with get(), release it from managed control with release(), and rebind it with reset(new_ptr). You can also incref it by calling inc(), but be cautious as you can easily create a leak by increfing once to much.

Python, 24 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <memory>

typedef std::auto_ptr<PyObject> auto_py_base;

class auto_py : public auto_py_base {
public:
	auto_py(PyObject * obj = NULL) : auto_py_base(obj) {
	}
	~auto_py() {
		reset();
	}
	void reset(PyObject * obj = NULL) {
		if(obj != get()) {
			PyObject * old = release(); // Avoid the delete call
			Py_XDECREF(old);
			auto_py_base::reset(obj);
		}
	}
	void inc() {
		PyObject * ptr = get();
		if(ptr)
			Py_INCREF(ptr);
	}
};

You can do most of this with boost::python, but that library doesn't give you full access to the Python C API, so when you need to pass around PyObject pointers this comes in handy.

1 comment

samh 12 years, 4 months ago  # | flag

I've found this to be quite useful, and I created a fork of this recipe with some slight modifications. Mainly, implementing an operator overload for casting to PyObject * allows you to pass it to Python API functions without calling get() every time (this seems like it might be slightly dangerous, but I haven't thought of any examples yet where it would be).

Created by Ian Eloff on Tue, 14 Aug 2007 (PSF)
Python recipes (4591)
Ian Eloff's recipes (3)

Required Modules

  • (none specified)

Other Information and Tasks