Merge lp:~bcatanzaro-w/pybindgen/shared_ptr into lp:~gjc/pybindgen/trunk

Proposed by Bryan Catanzaro
Status: Merged
Merged at revision: 882
Proposed branch: lp:~bcatanzaro-w/pybindgen/shared_ptr
Merge into: lp:~gjc/pybindgen/trunk
Diff against target: 252 lines (+192/-3)
6 files modified
examples/std_shared_ptr/modulegen.py (+47/-0)
examples/std_shared_ptr/sp.cc (+16/-0)
examples/std_shared_ptr/sp.h (+36/-0)
examples/std_shared_ptr/sp_test.py (+23/-0)
examples/std_shared_ptr/wscript (+22/-0)
pybindgen/cppclass.py (+48/-3)
To merge this branch: bzr merge lp:~bcatanzaro-w/pybindgen/shared_ptr
Reviewer Review Type Date Requested Status
Gustavo Carneiro Approve
Review via email: mp+232644@code.launchpad.net

Description of the change

Adds a memory policy for C++11's std::shared_ptr.
I've added a test to the examples directory, but waf isn't working on my system correctly and I don't have time to figure out why not, so I believe the wscript is likely to fail: to compile this code, one needs to enable C++11, which can require adding some compiler flags (such as -std=c++11 for g++).

To post a comment you must log in.
Revision history for this message
Gustavo Carneiro (gjc) wrote :

This was merged. Thank you!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'examples/std_shared_ptr'
2=== added file 'examples/std_shared_ptr/modulegen.py'
3--- examples/std_shared_ptr/modulegen.py 1970-01-01 00:00:00 +0000
4+++ examples/std_shared_ptr/modulegen.py 2014-08-28 21:12:21 +0000
5@@ -0,0 +1,47 @@
6+#! /usr/bin/env python
7+
8+import sys, os
9+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
10+ '..', '..'))
11+
12+#import pybindgen
13+#import pybindgen.utils
14+#from pybindgen.typehandlers import base as typehandlers
15+from pybindgen import Module, FileCodeSink, param, retval
16+#from pybindgen import CppMethod, CppConstructor, CppClass, Enum
17+#from pybindgen.function import CustomFunctionWrapper
18+#from pybindgen.cppmethod import CustomCppMethodWrapper
19+from pybindgen import cppclass
20+
21+#from pybindgen import param, retval
22+
23+import pybindgen.settings
24+pybindgen.settings.deprecated_virtuals = False
25+
26+
27+def my_module_gen(out_file):
28+
29+ mod = Module('sp')
30+
31+ mod.add_include ('"sp.h"')
32+
33+ Foo = mod.add_class('Foo', memory_policy=cppclass.SharedPtr('::Foo'))
34+
35+ Foo.add_constructor([param('std::string', 'datum')])
36+ Foo.add_constructor([])
37+ Foo.add_method('get_datum', retval('const std::string'), [])
38+ Foo.add_method('set_datum', None, [param('const std::string', 'datum')])
39+
40+
41+ mod.add_function('function_that_takes_foo', None,
42+ [param('std::shared_ptr<Foo>', 'foo')])
43+
44+ mod.add_function('function_that_returns_foo', retval('std::shared_ptr<Foo>'), [])
45+
46+ ## ---- finally, generate the whole thing ----
47+ mod.generate(FileCodeSink(out_file))
48+
49+
50+if __name__ == '__main__':
51+ my_module_gen(sys.stdout)
52+
53
54=== added file 'examples/std_shared_ptr/sp.cc'
55--- examples/std_shared_ptr/sp.cc 1970-01-01 00:00:00 +0000
56+++ examples/std_shared_ptr/sp.cc 2014-08-28 21:12:21 +0000
57@@ -0,0 +1,16 @@
58+#include "sp.h"
59+
60+std::shared_ptr<Foo> g_foo;
61+
62+void function_that_takes_foo(std::shared_ptr<Foo> foo)
63+{
64+ g_foo = foo;
65+}
66+
67+std::shared_ptr<Foo> function_that_returns_foo()
68+{
69+ return g_foo;
70+}
71+
72+
73+
74
75=== added file 'examples/std_shared_ptr/sp.h'
76--- examples/std_shared_ptr/sp.h 1970-01-01 00:00:00 +0000
77+++ examples/std_shared_ptr/sp.h 2014-08-28 21:12:21 +0000
78@@ -0,0 +1,36 @@
79+// -*- Mode: C++; c-file-style: "stroustrup"; indent-tabs-mode:nil; -*-
80+#ifndef SP_H_
81+# define SP_H_
82+
83+#include <string>
84+#include <iostream>
85+#include <memory>
86+
87+
88+class Foo
89+{
90+ std::string m_datum;
91+public:
92+
93+ Foo () : m_datum ("") {
94+ std::cout << "Created empty foo" << std::endl;
95+ }
96+
97+ Foo (std::string const &datum) : m_datum (datum) {
98+ std::cout << "Created foo with datum " << datum << std::endl;
99+ }
100+
101+ const std::string get_datum () const { return m_datum; }
102+
103+ void set_datum (std::string const &datum) { m_datum = datum; }
104+
105+ virtual ~Foo() {
106+ std::cout << "Destroyed foo with datum " << m_datum << std::endl;
107+ }
108+
109+};
110+
111+void function_that_takes_foo (std::shared_ptr<Foo> foo);
112+std::shared_ptr<Foo> function_that_returns_foo ();
113+
114+#endif /* !FOO_H_ */
115
116=== added file 'examples/std_shared_ptr/sp_test.py'
117--- examples/std_shared_ptr/sp_test.py 1970-01-01 00:00:00 +0000
118+++ examples/std_shared_ptr/sp_test.py 2014-08-28 21:12:21 +0000
119@@ -0,0 +1,23 @@
120+import sys
121+import os.path
122+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
123+ '..', '..', 'build', 'examples', 'boost_shared_ptr'))
124+
125+import sp
126+
127+def factory():
128+ return sp.Foo('factory')
129+
130+def use():
131+ a = factory()
132+ print a.get_datum()
133+
134+use()
135+
136+f = sp.Foo("hello123")
137+sp.function_that_takes_foo(f)
138+f1 = sp.function_that_returns_foo()
139+print f1.get_datum()
140+f.set_datum("xxxx")
141+print f1.get_datum()
142+
143
144=== added file 'examples/std_shared_ptr/wscript'
145--- examples/std_shared_ptr/wscript 1970-01-01 00:00:00 +0000
146+++ examples/std_shared_ptr/wscript 2014-08-28 21:12:21 +0000
147@@ -0,0 +1,22 @@
148+## -*- python -*-
149+
150+def build(bld):
151+
152+ gen = bld(
153+ features='command',
154+ source='modulegen.py',
155+ target='spmodule.cc',
156+ command='${PYTHON} ${SRC[0]} > ${TGT[0]}')
157+
158+ if bld.env['CXX']:
159+ # TODO() ADD -std=c++11 flag so that <memory>
160+ # contains std::shared_ptr
161+ obj = bld(features=['cxx', 'cxxshlib', 'pyext'])
162+ obj.source = [
163+ 'sp.cc',
164+ 'spmodule.cc'
165+ ]
166+ obj.target = 'sp'
167+ obj.install_path = None # do not install
168+ obj.includes = '.'
169+
170
171=== modified file 'pybindgen/cppclass.py'
172--- pybindgen/cppclass.py 2014-08-07 21:08:13 +0000
173+++ pybindgen/cppclass.py 2014-08-28 21:12:21 +0000
174@@ -222,6 +222,28 @@
175 def get_pystruct_init_code(self, cpp_class, obj):
176 return "new(&%s->obj) %s;" % (obj, self.pointer_name,)
177
178+class SharedPtr(SmartPointerPolicy):
179+ def __init__(self, class_name):
180+ """
181+ Create a memory policy for using std::shared_ptr<> to manage instances of this object.
182+
183+ :param class_name: the full name of the class, e.g. foo::Bar
184+ """
185+ self.class_name = class_name
186+ self.pointer_name = '::std::shared_ptr< %s >' % (self.class_name,)
187+
188+ def get_delete_code(self, cpp_class):
189+ return "self->obj.~shared_ptr< %s >();" % (self.class_name,)
190+
191+ def get_pointer_type(self, class_full_name):
192+ return self.pointer_name + ' '
193+
194+ def get_instance_creation_function(self):
195+ return std_shared_ptr_instance_creation_function
196+
197+ def get_pystruct_init_code(self, cpp_class, obj):
198+ return "new(&%s->obj) %s;" % (obj, self.pointer_name,)
199+
200
201 def default_instance_creation_function(cpp_class, code_block, lvalue,
202 parameters, construct_type_name):
203@@ -269,6 +291,28 @@
204 code_block.write_code(
205 "%s.reset (new %s(%s));" % (lvalue, construct_type_name, parameters))
206
207+def std_shared_ptr_instance_creation_function(cpp_class, code_block, lvalue,
208+ parameters, construct_type_name):
209+ """
210+ std::shared_ptr "instance creation function"; it is called whenever a new
211+ C++ class instance needs to be created
212+
213+ :param cpp_class: the CppClass object whose instance is to be created
214+ :param code_block: CodeBlock object on which the instance creation code should be generated
215+ :param lvalue: lvalue expression that should hold the result in the end
216+ :param parameters: stringified list of parameters
217+ :param construct_type_name: actual name of type to be constructed (it is
218+ not always the class name, sometimes it's
219+ the python helper class)
220+ """
221+ assert lvalue
222+ assert not lvalue.startswith('None')
223+ if cpp_class.incomplete_type:
224+ raise CodeGenerationError("%s cannot be constructed (incomplete type)"
225+ % cpp_class.full_name)
226+ code_block.write_code(
227+ "%s = std::make_shared<%s>(%s);" % (lvalue, construct_type_name, parameters))
228+
229
230
231 class CppHelperClass(object):
232@@ -785,7 +829,7 @@
233 except ValueError:
234 pass
235
236- if isinstance(self.memory_policy, BoostSharedPtr): # boost::shared_ptr<Class>
237+ if isinstance(self.memory_policy, SmartPointerPolicy): # boost::shared_ptr<Class> or std::shared_ptr<Class>
238
239 class ThisClassSharedPtrParameter(CppClassSharedPtrParameter):
240 """Register this C++ class as pass-by-pointer parameter"""
241@@ -1263,8 +1307,9 @@
242 return_type_matcher.register(alias, self.ThisClassReturn)
243 except ValueError: pass
244
245- if isinstance(self.memory_policy, BoostSharedPtr):
246- alias_ptr = 'boost::shared_ptr< %s >' % alias
247+ if isinstance(self.memory_policy, SmartPointerPolicy):
248+ alias_ptr = self.memory_policy.__class__(alias).pointer_name
249+ #alias_ptr = 'boost::shared_ptr< %s >' % alias
250 self.ThisClassSharedPtrParameter.CTYPES.append(alias_ptr)
251 try:
252 param_type_matcher.register(alias_ptr, self.ThisClassSharedPtrParameter)

Subscribers

People subscribed via source and target branches