Skip to content

Commit 68f54d3

Browse files
author
Bruno da Silva de Oliveira
committed
- register_ptr_to_python addition
[SVN r18880]
1 parent 7dba18e commit 68f54d3

6 files changed

Lines changed: 282 additions & 0 deletions

File tree

doc/v2/reference.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,22 @@ <h2><a name="type_conversion">To/From Python Type Conversion</a></h2>
973973
</dd>
974974
</dl>
975975
</dd>
976+
977+
<dt><a href="register_ptr_to_python.html">register_ptr_to_python.hpp</a></dt>
978+
979+
<dd>
980+
<dl class="index">
981+
<dt><a href="register_ptr_to_python.html#functions">Functions</a></dt>
982+
983+
<dd>
984+
<dl class="index">
985+
<dt><a href=
986+
"register_ptr_to_python.html#register_ptr_to_python-spec">register_ptr_to_python</a></dt>
987+
</dl>
988+
</dd>
989+
</dl>
990+
</dd>
991+
976992
</dl>
977993

978994
<h2><a name="utility">Utility and Infrastructure</a></h2>

doc/v2/register_ptr_to_python.html

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
<html>
2+
<head>
3+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
4+
<link rel="stylesheet" type="text/css" href="../boost.css">
5+
<title>Boost.Python - &lt;register_ptr_to_python.hpp&gt;</title>
6+
</head>
7+
<body link="#0000ff" vlink="#800080">
8+
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
9+
"header">
10+
<tr>
11+
<td valign="top" width="300">
12+
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
13+
"C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
14+
</td>
15+
<td valign="top">
16+
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
17+
<h2 align="center">Header &lt;register_ptr_to_python.hpp&gt;</h2>
18+
</td>
19+
</tr>
20+
</table>
21+
<hr>
22+
<h2>Contents</h2>
23+
<dl class="page-index">
24+
<dt><a href="#introduction">Introduction</a></dt>
25+
<dt><a href="#functions">Functions</a></dt>
26+
<dl class="page-index">
27+
<dt><a href="#register_ptr_to_python-spec">register_ptr_to_python</a></dt>
28+
</dl>
29+
30+
<dt><a href="#examples">Example(s)</a></dt>
31+
32+
</dl>
33+
<hr>
34+
<h2><a name="introduction"></a>Introduction</h2>
35+
<p>
36+
<code>&lt;boost/python/converter/register_ptr_to_python.hpp&gt;</code>
37+
supplies <code>register_ptr_to_python</code>, a function template
38+
which registers a conversion for smart pointers to Python. The
39+
resulting Python object holds a copy of the converted smart pointer,
40+
but behaves as though it were a wrapped copy of the pointee. If
41+
the pointee type has virtual functions and the class representing
42+
its dynamic (most-derived) type has been wrapped, the Python object
43+
will be an instance of the wrapper for the most-derived type. More than
44+
one smart pointer type for a pointee's class can be registered.
45+
</p>
46+
<p>
47+
Note that in order to convert a Python <code>X</code> object to a
48+
<code>smart_ptr&lt;X&gt;&amp;</code> (non-const reference), the embedded C++
49+
object must be held by <code>smart_ptr&lt;X&gt;</code>, and that when wrapped
50+
objects are created by calling the constructor from Python, how they are held
51+
is determined by the <code>HeldType</code> parameter to class_&lt;...&gt;
52+
instances.
53+
</p>
54+
55+
<h2><a name="functions"></a>Functions</h2>
56+
<pre>
57+
<a name="register_ptr_to_python-spec">template &lt;class P&gt;
58+
void register_ptr_to_python()
59+
</pre>
60+
<dl class="function-semantics">
61+
<dt><b>Requires:</b> <code>P</code> is the type of the smart pointer,
62+
for example <code>smart_ptr&lt;X&gt;</code>.
63+
</dt>
64+
<dt><b>Effects:</b> Allows conversions to-python of <code>smart_ptr&lt;X&gt;</code>
65+
instances.
66+
</dt>
67+
</dl>
68+
69+
<h2><a name="examples"></a>Example(s)</h2>
70+
71+
<h3>C++ Wrapper Code</h3>
72+
73+
Here is an example of a module that contains a class <code>A</code> with
74+
virtual functions and some functions that work with
75+
<code>boost::shared_ptr&lt;A&gt;</code>.
76+
77+
<pre>
78+
struct A
79+
{
80+
virtual int f() { return 0; }
81+
};
82+
83+
shared_ptr&lt;A&gt; New() { return shared_ptr&lt;A&gt;( new A() ); }
84+
85+
int Ok( const shared_ptr&lt;A&gt;&amp; a ) { return a-&gt;f(); }
86+
87+
int Fail( shared_ptr&lt;A&gt;&amp; a ) { return a-&gt;f(); }
88+
89+
struct A_Wrapper: A
90+
{
91+
A_Wrapper(PyObject* self_): self(self_) {}
92+
int f() { return call_method&lt;int&gt;(self, "f"); }
93+
int default_f() { return A::f(); }
94+
PyObject* self;
95+
};
96+
97+
BOOST_PYTHON_MODULE(register_ptr)
98+
{
99+
class_&lt;A, A_Wrapper&gt;("A")
100+
.def("f", &amp;A::f, &amp;A_Wrapper::default_f)
101+
;
102+
103+
def("New", &amp;New);
104+
def("Ok", &amp;Call);
105+
def("Fail", &amp;Fail);
106+
107+
register_ptr_to_python&lt; shared_ptr&lt;A&gt; &gt;();
108+
}
109+
</pre>
110+
111+
<h3>Python Code</h3>
112+
113+
<pre>
114+
&gt;&gt;&gt; from register_ptr import *
115+
&gt;&gt;&gt; a = A()
116+
&gt;&gt;&gt; Ok(a) # ok, passed as shared_ptr&lt;A&gt;
117+
0
118+
&gt;&gt;&gt; Fail(a) # passed as shared_ptr&lt;A&gt;&amp;, and was created in Python!
119+
Traceback (most recent call last):
120+
File "&lt;stdin&gt;", line 1, in ?
121+
TypeError: bad argument type for built-in operation
122+
&gt;&gt;&gt;
123+
&gt;&gt;&gt; na = New() # now "na" is actually a shared_ptr&lt;A&gt;
124+
&gt;&gt;&gt; Ok(a)
125+
0
126+
&gt;&gt;&gt; Fail(a)
127+
0
128+
&gt;&gt;&gt;
129+
</pre>
130+
131+
If <code>shared_ptr&lt;A&gt;</code> is registered as follows:
132+
133+
<pre>
134+
class_&lt;A, A_Wrapper, shared_ptr&lt;A&gt; &gt;("A")
135+
.def("f", &amp;A::f, &amp;A_Wrapper::default_f)
136+
;
137+
</pre>
138+
139+
There will be an error when trying to convert <code>shared_ptr&lt;A&gt;</code> to
140+
<code>shared_ptr&lt;A_Wrapper&gt;</code>:
141+
142+
<pre>
143+
&gt;&gt;&gt; a = New()
144+
Traceback (most recent call last):
145+
File "&lt;stdin&gt;", line 1, in ?
146+
TypeError: No to_python (by-value) converter found for C++ type: class boost::shared_ptr&lt;struct A&gt;
147+
&gt;&gt;&gt;
148+
</pre>
149+
150+
<p>Revised
151+
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
152+
24 Jun, 2003
153+
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
154+
</p>
155+
<p><i>&copy; Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
156+
2002. All Rights Reserved.</i></p>
157+
</body>
158+
</html>
159+
160+

include/boost/python.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,6 @@
6363
# include <boost/python/tuple.hpp>
6464
# include <boost/python/type_id.hpp>
6565
# include <boost/python/with_custodian_and_ward.hpp>
66+
# include <boost/python/converter/register_ptr_to_python.hpp>
6667

6768
#endif // PYTHON_DWA2002810_HPP
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright David Abrahams 2002. Permission to copy, use,
2+
// modify, sell and distribute this software is granted provided this
3+
// copyright notice appears in all copies. This software is provided
4+
// "as is" without express or implied warranty, and with no claim as
5+
// to its suitability for any purpose.
6+
#ifndef REGISTER_PTR_TO_PYTHON_HPP
7+
#define REGISTER_PTR_TO_PYTHON_HPP
8+
9+
#include <boost/python/pointee.hpp>
10+
#include <boost/python/object.hpp>
11+
12+
namespace boost { namespace python {
13+
14+
template <class P>
15+
void register_ptr_to_python(P* = 0)
16+
{
17+
typedef typename boost::python::pointee<P>::type X;
18+
objects::class_value_wrapper<
19+
P
20+
, objects::make_ptr_instance<
21+
X
22+
, objects::pointer_holder<P,X>
23+
>
24+
>();
25+
}
26+
27+
}} // namespace boost::python
28+
29+
#endif // REGISTER_PTR_TO_PYTHON_HPP
30+
31+

test/register_ptr.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
2+
#include <boost/python.hpp>
3+
#include <boost/shared_ptr.hpp>
4+
5+
using namespace boost;
6+
using namespace python;
7+
8+
struct A
9+
{
10+
virtual int f() { return 0; }
11+
};
12+
13+
shared_ptr<A> New() { return shared_ptr<A>( new A() ); }
14+
15+
int Call( const shared_ptr<A> & a )
16+
{
17+
return a->f();
18+
}
19+
20+
int Fail( shared_ptr<A> & a )
21+
{
22+
return a->f();
23+
}
24+
25+
struct A_Wrapper: A
26+
{
27+
A_Wrapper(PyObject* self_): self(self_) {}
28+
A_Wrapper(PyObject* self_, const A& a): self(self_), A(a) {}
29+
30+
int f()
31+
{
32+
return call_method<int>(self, "f");
33+
}
34+
35+
int default_f()
36+
{
37+
return A::f();
38+
}
39+
40+
PyObject* self;
41+
};
42+
43+
BOOST_PYTHON_MODULE(register_ptr)
44+
{
45+
class_<A, A_Wrapper>("A")
46+
.def("f", &A::f, &A_Wrapper::default_f)
47+
;
48+
register_ptr_to_python< shared_ptr<A> >();
49+
def("New", &New);
50+
def("Call", &Call);
51+
def("Fail", &Fail);
52+
}

test/register_ptr_test.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import unittest
2+
from register_ptr import *
3+
4+
class RegisterPtrTest(unittest.TestCase):
5+
6+
def testIt(self):
7+
8+
class B(A):
9+
def f(self):
10+
return 10
11+
12+
a = New() # this must work
13+
b = B()
14+
self.assertEqual(Call(a), 0)
15+
self.assertEqual(Call(b), 10)
16+
def fails():
17+
Fail(A())
18+
self.assertRaises(TypeError, fails)
19+
self.assertEqual(Fail(a), 0) # ok, since a is held by shared_ptr
20+
21+
if __name__ == '__main__':
22+
unittest.main()

0 commit comments

Comments
 (0)