<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=US-ASCII">
<META NAME="Generator" CONTENT="MS Exchange Server version 5.5.2653.12">
<TITLE>AW: [C++-sig] Wrapping opaque pointers returned from API functions</TITLE>
</HEAD>
<BODY>
<P><FONT SIZE=2>... </FONT>
<BR><FONT SIZE=2>> Obviously, wrapping opaque pointers is a common thing to want to do,</FONT>
<BR><FONT SIZE=2>> and the library should provide a better facility for it.</FONT>
<BR><FONT SIZE=2>I made one up for my own use, see below.</FONT>
<BR><FONT SIZE=2>This reduces my sample to</FONT>
</P>
<P><FONT SIZE=2># include "pointer_converter.h"</FONT>
<BR><FONT SIZE=2># include <boost/python/def.hpp></FONT>
<BR><FONT SIZE=2># include <boost/python/module.hpp></FONT>
<BR><FONT SIZE=2># include <boost/python/return_by_value.hpp></FONT>
<BR><FONT SIZE=2># include <boost/python/return_value_policy.hpp></FONT>
</P>
<P><FONT SIZE=2>using namespace boost::python;</FONT>
</P>
<P><FONT SIZE=2># include <iostream></FONT>
</P>
<P><FONT SIZE=2>typedef struct workspace_ *workspace;</FONT>
</P>
<P><FONT SIZE=2>workspace osr_init (const char *) { return ((workspace) 0x47110815); }</FONT>
<BR><FONT SIZE=2>void osr_exit (workspace ws) { std::cerr << ws << std::endl; }</FONT>
</P>
<P><FONT SIZE=2>BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(workspace_)</FONT>
<BR><FONT SIZE=2>DEFINE_POINTER_CONVERTER(workspace)</FONT>
</P>
<P><FONT SIZE=2>BOOST_PYTHON_MODULE(_pyOSR)</FONT>
<BR><FONT SIZE=2>{</FONT>
<BR><FONT SIZE=2> REGISTER_POINTER_CONVERTER(workspace);</FONT>
</P>
<P><FONT SIZE=2> def ("osr_init", &::osr_init, return_value_policy<return_by_value>());</FONT>
<BR><FONT SIZE=2> def ("osr_exit", &::osr_exit);</FONT>
<BR><FONT SIZE=2>}</FONT>
</P>
<P><FONT SIZE=2>I'm not really content with the macro implementation but couldn't see another implementation easily.</FONT>
</P>
<P><FONT SIZE=2>Cheers,</FONT>
</P>
<P><FONT SIZE=2>Gottfried</FONT>
</P>
<P><FONT SIZE=2>-------------><-----------------------><------------------------><--------------------><-------------</FONT>
<BR><FONT SIZE=2>/*</FONT>
<BR><FONT SIZE=2> * file: pointer_converter.h</FONT>
<BR><FONT SIZE=2> * date: 2003-01-10</FONT>
<BR><FONT SIZE=2> * Copyright C 2003 Haufe Mediengruppe</FONT>
<BR><FONT SIZE=2> *</FONT>
<BR><FONT SIZE=2> * Generic Conversion of opaque C++-pointers to a Python-</FONT>
<BR><FONT SIZE=2> * Wrapper.</FONT>
<BR><FONT SIZE=2> *</FONT>
<BR><FONT SIZE=2> * $Id$</FONT>
<BR><FONT SIZE=2> */</FONT>
<BR><FONT SIZE=2># include <boost/python/lvalue_from_pytype.hpp></FONT>
<BR><FONT SIZE=2># include <boost/python/pointee.hpp></FONT>
<BR><FONT SIZE=2># include <boost/python/to_python_converter.hpp></FONT>
</P>
<P><FONT SIZE=2>/**</FONT>
<BR><FONT SIZE=2> * Declare a converter which will convert a C++-Pointer to an</FONT>
<BR><FONT SIZE=2> * opaque structure to a Python object containing the pointer</FONT>
<BR><FONT SIZE=2> * and vice versa.</FONT>
<BR><FONT SIZE=2> *</FONT>
<BR><FONT SIZE=2> * @param P</FONT>
<BR><FONT SIZE=2> * Pointer type to wrap</FONT>
<BR><FONT SIZE=2> *</FONT>
<BR><FONT SIZE=2> * @note</FONT>
<BR><FONT SIZE=2> * In addition you need to define specializations for type_traits</FONT>
<BR><FONT SIZE=2> * using BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</FONT>
<BR><FONT SIZE=2> * </FONT>
<BR><FONT SIZE=2> * @see type_traits documentation</FONT>
<BR><FONT SIZE=2> */</FONT>
<BR><FONT SIZE=2># define DEFINE_POINTER_CONVERTER(P) \</FONT>
<BR><FONT SIZE=2>namespace { \</FONT>
<BR><FONT SIZE=2> template <class Pointer> \</FONT>
<BR><FONT SIZE=2> struct pointer_converter \</FONT>
<BR><FONT SIZE=2> : PyObject, \</FONT>
<BR><FONT SIZE=2> to_python_converter< \</FONT>
<BR><FONT SIZE=2> typename Pointer, pointer_converter<Pointer> > \</FONT>
<BR><FONT SIZE=2> { \</FONT>
<BR><FONT SIZE=2> \</FONT>
<BR><FONT SIZE=2> pointer_converter() { \</FONT>
<BR><FONT SIZE=2> lvalue_from_pytype< \</FONT>
<BR><FONT SIZE=2> pointer_converter, &pointer_converter::type>(); \</FONT>
<BR><FONT SIZE=2> } \</FONT>
<BR><FONT SIZE=2> \</FONT>
<BR><FONT SIZE=2> static PyObject* convert(Pointer x) { \</FONT>
<BR><FONT SIZE=2> pointer_converter *o = \</FONT>
<BR><FONT SIZE=2> PyObject_New ( \</FONT>
<BR><FONT SIZE=2> pointer_converter, &pointer_converter::type); \</FONT>
<BR><FONT SIZE=2> \</FONT>
<BR><FONT SIZE=2> o->x = x; \</FONT>
<BR><FONT SIZE=2> return ((PyObject*) o); \</FONT>
<BR><FONT SIZE=2> } \</FONT>
<BR><FONT SIZE=2> \</FONT>
<BR><FONT SIZE=2> static boost::python::pointee<Pointer>::type &execute ( \</FONT>
<BR><FONT SIZE=2> pointer_converter<Pointer> &p_) { \</FONT>
<BR><FONT SIZE=2> return *p_.x; \</FONT>
<BR><FONT SIZE=2> } \</FONT>
<BR><FONT SIZE=2> \</FONT>
<BR><FONT SIZE=2> static void dealloc(PyObject* self) { \</FONT>
<BR><FONT SIZE=2> PyObject_Del(self); \</FONT>
<BR><FONT SIZE=2> } \</FONT>
<BR><FONT SIZE=2> private: \</FONT>
<BR><FONT SIZE=2> typename Pointer x; \</FONT>
<BR><FONT SIZE=2> static PyTypeObject type; \</FONT>
<BR><FONT SIZE=2> }; \</FONT>
<BR><FONT SIZE=2> \</FONT>
<BR><FONT SIZE=2> PyTypeObject pointer_converter<P>::type = { \</FONT>
<BR><FONT SIZE=2> PyObject_HEAD_INIT(NULL) \</FONT>
<BR><FONT SIZE=2> 0, \</FONT>
<BR><FONT SIZE=2> # P, \</FONT>
<BR><FONT SIZE=2> sizeof(pointer_converter<P>), \</FONT>
<BR><FONT SIZE=2> 0, \</FONT>
<BR><FONT SIZE=2> pointer_converter<P>::dealloc \</FONT>
<BR><FONT SIZE=2> }; \</FONT>
<BR><FONT SIZE=2>}</FONT>
</P>
<P><FONT SIZE=2>/**</FONT>
<BR><FONT SIZE=2> * register a pointer converter with the boost.python</FONT>
<BR><FONT SIZE=2> * converter registry.</FONT>
<BR><FONT SIZE=2> * This needs to go into the <module>_init function.</FONT>
<BR><FONT SIZE=2> *</FONT>
<BR><FONT SIZE=2> * @param P</FONT>
<BR><FONT SIZE=2> * Pointer type wrapped by a pointer converter with</FONT>
<BR><FONT SIZE=2> * DEFINE_POINTER_CONVERTER.</FONT>
<BR><FONT SIZE=2> *</FONT>
<BR><FONT SIZE=2> * @see DEFINE_POINTER_CONVERTER</FONT>
<BR><FONT SIZE=2> */</FONT>
<BR><FONT SIZE=2># define REGISTER_POINTER_CONVERTER(P) pointer_converter<P>()</FONT>
</P>
</BODY>
</HTML>