1 //
2 // Copyright (c) 2008-2010 Barry A. Scott
3 //
4 //
5 // simple_moduile.cxx
6 //
7 // This module defines a single function.
8 //
9 #ifdef _MSC_VER
10 // disable warning C4786: symbol greater than 255 character,
11 // nessesary to ignore as <map> causes lots of warning
12 #pragma warning(disable: 4786)
13 #endif
14
15 #include "CXX/Objects.hxx"
16 #include "CXX/Extensions.hxx"
17
18 #include <assert.h>
19
20 class new_style_class: public Py::PythonClass< new_style_class >
21 {
22 public:
new_style_class(Py::PythonClassInstance * self,Py::Tuple & args,Py::Dict & kwds)23 new_style_class( Py::PythonClassInstance *self, Py::Tuple &args, Py::Dict &kwds )
24 : Py::PythonClass< new_style_class >::PythonClass( self, args, kwds )
25 , m_value( "default value" )
26 {
27 std::cout << "new_style_class c'tor Called with " << args.length() << " normal arguments." << std::endl;
28 Py::List names( kwds.keys() );
29 std::cout << "and with " << names.length() << " keyword arguments:" << std::endl;
30 for( Py::List::size_type i=0; i< names.length(); i++ )
31 {
32 Py::String name( names[i] );
33 std::cout << " " << name << std::endl;
34 }
35 }
36
~new_style_class()37 virtual ~new_style_class()
38 {
39 std::cout << "~new_style_class." << std::endl;
40 }
41
cxx_method(long a,long b)42 long cxx_method( long a, long b )
43 {
44 return a * b + 3;
45 }
46
init_type(void)47 static void init_type(void)
48 {
49 behaviors().name( "new_style_class" );
50 behaviors().doc( "documentation for new_style_class class" );
51 behaviors().supportGetattro();
52 behaviors().supportSetattro();
53
54 PYCXX_ADD_NOARGS_METHOD( func_noargs, new_style_class_func_noargs, "docs for new_style_class_func_noargs" );
55 PYCXX_ADD_VARARGS_METHOD( func_varargs, new_style_class_func_varargs, "docs for new_style_class_func_varargs" );
56 PYCXX_ADD_KEYWORDS_METHOD( func_keyword, new_style_class_func_keyword, "docs for new_style_class_func_keyword" );
57
58 PYCXX_ADD_NOARGS_METHOD( func_noargs_raise_exception, new_style_class_func_noargs_raise_exception, "docs for new_style_class_func_noargs_raise_exception" );
59
60 // Call to make the type ready for use
61 behaviors().readyType();
62 }
63
new_style_class_func_noargs(void)64 Py::Object new_style_class_func_noargs( void )
65 {
66 std::cout << "new_style_class_func_noargs Called." << std::endl;
67 std::cout << "value ref count " << m_value.reference_count() << std::endl;
68 return Py::None();
69 }
PYCXX_NOARGS_METHOD_DECL(new_style_class,new_style_class_func_noargs)70 PYCXX_NOARGS_METHOD_DECL( new_style_class, new_style_class_func_noargs )
71
72 Py::Object new_style_class_func_varargs( const Py::Tuple &args )
73 {
74 std::cout << "new_style_class_func_varargs Called with " << args.length() << " normal arguments." << std::endl;
75 return Py::None();
76 }
PYCXX_VARARGS_METHOD_DECL(new_style_class,new_style_class_func_varargs)77 PYCXX_VARARGS_METHOD_DECL( new_style_class, new_style_class_func_varargs )
78
79 Py::Object new_style_class_func_keyword( const Py::Tuple &args, const Py::Dict &kwds )
80 {
81 std::cout << "new_style_class_func_keyword Called with " << args.length() << " normal arguments." << std::endl;
82 Py::List names( kwds.keys() );
83 std::cout << "and with " << names.length() << " keyword arguments:" << std::endl;
84 for( Py::List::size_type i=0; i< names.length(); i++ )
85 {
86 Py::String name( names[i] );
87 std::cout << " " << name << std::endl;
88 }
89 return Py::None();
90 }
PYCXX_KEYWORDS_METHOD_DECL(new_style_class,new_style_class_func_keyword)91 PYCXX_KEYWORDS_METHOD_DECL( new_style_class, new_style_class_func_keyword )
92
93 Py::Object new_style_class_func_noargs_raise_exception( void )
94 {
95 std::cout << "new_style_class_func_noargs_raise_exception Called." << std::endl;
96 throw Py::RuntimeError( "its an error" );
97 }
PYCXX_NOARGS_METHOD_DECL(new_style_class,new_style_class_func_noargs_raise_exception)98 PYCXX_NOARGS_METHOD_DECL( new_style_class, new_style_class_func_noargs_raise_exception )
99
100 Py::Object getattro( const Py::String &name_ )
101 {
102 std::string name( name_.as_std_string( "utf-8" ) );
103
104 if( name == "value" )
105 {
106 return m_value;
107 }
108 else
109 {
110 return genericGetAttro( name_ );
111 }
112 }
113
setattro(const Py::String & name_,const Py::Object & value)114 int setattro( const Py::String &name_, const Py::Object &value )
115 {
116 std::string name( name_.as_std_string( "utf-8" ) );
117
118 if( name == "value" )
119 {
120 m_value = value;
121 return 0;
122 }
123 else
124 {
125 return genericSetAttro( name_, value );
126 }
127 }
128
129 Py::String m_value;
130 };
131
132
133 class old_style_class: public Py::PythonExtension< old_style_class >
134 {
135 public:
old_style_class()136 old_style_class()
137 {
138 }
139
~old_style_class()140 virtual ~old_style_class()
141 {
142 }
143
init_type(void)144 static void init_type(void)
145 {
146 behaviors().name( "old_style_class" );
147 behaviors().doc( "documentation for old_style_class class" );
148 behaviors().supportGetattr();
149
150 add_noargs_method( "old_style_class_func_noargs", &old_style_class::old_style_class_func_noargs );
151 add_varargs_method( "old_style_class_func_varargs", &old_style_class::old_style_class_func_varargs );
152 add_keyword_method( "old_style_class_func_keyword", &old_style_class::old_style_class_func_keyword );
153 }
154
155 // override functions from PythonExtension
getattr(const char * name)156 virtual Py::Object getattr( const char *name )
157 {
158 return getattr_methods( name );
159 }
160
old_style_class_func_noargs(void)161 Py::Object old_style_class_func_noargs( void )
162 {
163 std::cout << "old_style_class_func_noargs Called." << std::endl;
164 return Py::None();
165 }
166
old_style_class_func_varargs(const Py::Tuple & args)167 Py::Object old_style_class_func_varargs( const Py::Tuple &args )
168 {
169 std::cout << "old_style_class_func_varargs Called with " << args.length() << " normal arguments." << std::endl;
170 return Py::None();
171 }
172
old_style_class_func_keyword(const Py::Tuple & args,const Py::Dict & kwds)173 Py::Object old_style_class_func_keyword( const Py::Tuple &args, const Py::Dict &kwds )
174 {
175 std::cout << "old_style_class_func_keyword Called with " << args.length() << " normal arguments." << std::endl;
176 Py::List names( kwds.keys() );
177 std::cout << "and with " << names.length() << " keyword arguments:" << std::endl;
178 for( Py::List::size_type i=0; i< names.length(); i++ )
179 {
180 Py::String name( names[i] );
181 std::cout << " " << name << std::endl;
182 }
183 return Py::None();
184 }
185 };
186
187 class simple_module : public Py::ExtensionModule<simple_module>
188 {
189 public:
simple_module()190 simple_module()
191 : Py::ExtensionModule<simple_module>( "simple" ) // this must be name of the file on disk e.g. simple.so or simple.pyd
192 {
193 old_style_class::init_type();
194 new_style_class::init_type();
195
196 add_noargs_method( "mod_func_noargs", &simple_module::mod_func_noargs, "documentation for mod_func_noargs()" );
197 add_varargs_method( "mod_func_varargs", &simple_module::mod_func_varargs, "documentation for mod_func_varargs()" );
198 add_keyword_method( "mod_func_keyword", &simple_module::mod_func_keyword, "documentation for mod_func_keyword()" );
199
200 add_varargs_method("old_style_class", &simple_module::factory_old_style_class, "documentation for old_style_class()");
201 add_keyword_method("make_instance", &simple_module::make_instance, "documentation for make_instance()");
202
203 add_keyword_method("decode_test", &simple_module::decode_test, "documentation for decode_test()");
204 add_keyword_method("encode_test", &simple_module::encode_test, "documentation for encode_test()");
205 add_keyword_method("derived_class_test", &simple_module::derived_class_test, "documentation for derived_class_test()");
206
207 // after initialize the moduleDictionary will exist
208 initialize( "documentation for the simple module" );
209
210 Py::Dict d( moduleDictionary() );
211 d["var"] = Py::String( "var value" );
212 Py::Object x( new_style_class::type() );
213 d["new_style_class"] = x;
214 }
215
~simple_module()216 virtual ~simple_module()
217 {}
218
219 private:
decode_test(const Py::Tuple & args,const Py::Dict &)220 Py::Object decode_test( const Py::Tuple &args, const Py::Dict &/*kwds*/ )
221 {
222 Py::String s( args[0] );
223 return s.decode("utf-8");
224 }
225
encode_test(const Py::Tuple & args,const Py::Dict &)226 Py::Object encode_test( const Py::Tuple &args, const Py::Dict &/*kwds*/ )
227 {
228 Py::String s( args[0] );
229 return s.encode("utf-8");
230 }
231
derived_class_test(const Py::Tuple & args,const Py::Dict &)232 Py::Object derived_class_test( const Py::Tuple &args, const Py::Dict &/*kwds*/ )
233 {
234 Py::PythonClassObject<new_style_class> py_nsc( args[0] );
235 new_style_class *cxx_nsc = py_nsc.getCxxObject();
236
237 Py::Long a( args[1] );
238 Py::Long b( args[2] );
239
240 long result = cxx_nsc->cxx_method( a, b );
241
242 return Py::Long( result );
243 }
244
mod_func_noargs()245 Py::Object mod_func_noargs()
246 {
247 std::cout << "mod_func_noargs Called." << std::endl;
248 return Py::None();
249 }
250
mod_func_varargs(const Py::Tuple & args)251 Py::Object mod_func_varargs( const Py::Tuple &args )
252 {
253 std::cout << "mod_func_varargs Called with " << args.length() << " normal arguments." << std::endl;
254 return Py::None();
255 }
256
mod_func_keyword(const Py::Tuple & args,const Py::Dict & kwds)257 Py::Object mod_func_keyword( const Py::Tuple &args, const Py::Dict &kwds )
258 {
259 std::cout << "mod_func_varargs Called with " << args.length() << " normal arguments." << std::endl;
260 Py::List names( kwds.keys() );
261 std::cout << "and with " << names.length() << " keyword arguments:" << std::endl;
262 for( Py::List::size_type i=0; i< names.length(); i++ )
263 {
264 Py::String name( names[i] );
265 std::cout << " " << name << std::endl;
266 }
267
268 if( args.length() > 0 )
269 {
270 Py::Object x( args[0] );
271 try
272 {
273 Py::PythonClassObject<new_style_class> x2( x );
274 std::cout << "C++ pointer " << x2.getCxxObject() << std::endl;
275 }
276 catch( Py::TypeError &e )
277 {
278 // must clear the error
279 e.clear();
280 std::cout << "arg 1 is not a new_style_class" << std::endl;
281 }
282 }
283
284 return Py::None();
285 }
286
make_instance(const Py::Tuple & args,const Py::Dict & kwds)287 Py::Object make_instance( const Py::Tuple &args, const Py::Dict &kwds )
288 {
289 std::cout << "make_instance Called with " << args.length() << " normal arguments." << std::endl;
290 Py::List names( kwds.keys() );
291 std::cout << "and with " << names.length() << " keyword arguments:" << std::endl;
292 for( Py::List::size_type i=0; i< names.length(); i++ )
293 {
294 Py::String name( names[i] );
295 std::cout << " " << name << std::endl;
296 }
297
298 Py::Callable class_type( new_style_class::type() );
299
300 Py::PythonClassObject<new_style_class> new_style_obj( class_type.apply( args, kwds ) );
301
302 return new_style_obj;
303 }
304
305
factory_old_style_class(const Py::Tuple &)306 Py::Object factory_old_style_class( const Py::Tuple &/*args*/ )
307 {
308 Py::Object obj = Py::asObject( new old_style_class );
309 return obj;
310 }
311 };
312
313 #if defined( _WIN32 )
314 #define EXPORT_SYMBOL __declspec( dllexport )
315 #else
316 #define EXPORT_SYMBOL
317 #endif
318
319 #if PY_MAJOR_VERSION == 3
320 static simple_module *simple;
321
PyInit_simple()322 extern "C" EXPORT_SYMBOL PyObject *PyInit_simple()
323 {
324 #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL)
325 Py::InitialisePythonIndirectPy::Interface();
326 #endif
327
328 simple = new simple_module;
329 return simple->module().ptr();
330 }
331
332 // symbol required for the debug version
PyInit_simple_d()333 extern "C" EXPORT_SYMBOL PyObject *PyInit_simple_d()
334 {
335 return PyInit_simple();
336 }
337
338 #else
339
340 static simple_module *simple;
341
initsimple()342 extern "C" EXPORT_SYMBOL void initsimple()
343 {
344 #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL)
345 Py::InitialisePythonIndirectPy::Interface();
346 #endif
347
348 simple = new simple_module;
349 }
350
351 // symbol required for the debug version
initsimple_d()352 extern "C" EXPORT_SYMBOL void initsimple_d()
353 {
354 initsimple();
355 }
356 #endif
357