Extensions.h
1//---------------------------------------------------------------------------//
2// Copyright 1998 The Regents of the University of California.
3// All rights reserved. See LEGAL.LLNL for full text and disclaimer.
4//---------------------------------------------------------------------------//
5
6#ifndef __CXX_Extensions__h
7#define __CXX_Extensions__h
8
9
10#ifdef _MSC_VER
11// disable warning C4786: symbol greater than 255 character,
12// okay to ignore
13#pragma warning(disable: 4786)
14#endif
15
16
17#include "Config.h"
18#include "Objects.h"
19
20extern "C"
21 {
22 extern PyObject py_object_initializer;
23 }
24
25#include <vector>
26#include <map>
27
28namespace Py
29 {
30 class ExtensionModuleBase;
31
32 // Make an Exception Type for use in raising custom exceptions
33 class ExtensionExceptionType : public Object
34 {
35 public:
36 ExtensionExceptionType();
37 virtual ~ExtensionExceptionType();
38
39 // call init to create the type
40 void init( ExtensionModuleBase &module, const std::string& name );
41 };
42
43
44 class MethodTable
45 {
46 public:
47 MethodTable();
48 virtual ~MethodTable();
49
50 void add(const char* method_name, PyCFunction f, const char* doc="", int flag=1);
51 PyMethodDef* table();
52
53 protected:
54 std::vector<PyMethodDef> t; // accumulator of PyMethodDef's
55 PyMethodDef *mt; // Actual method table produced when full
56
57 static PyMethodDef method (const char* method_name, PyCFunction f, int flags = 1, const char* doc="");
58
59 private:
60 //
61 // prevent the compiler generating these unwanted functions
62 //
63 MethodTable(const MethodTable& m); //unimplemented
64 void operator=(const MethodTable& m); //unimplemented
65
66 }; // end class MethodTable
67
68 extern "C"
69 {
70 typedef PyObject *(*method_varargs_call_handler_t)( PyObject *_self, PyObject *_args );
71 typedef PyObject *(*method_keyword_call_handler_t)( PyObject *_self, PyObject *_args, PyObject *_dict );
72 }
73
74 template<class T>
75 class MethodDefExt : public PyMethodDef
76 {
77 public:
78 typedef Object (T::*method_varargs_function_t)( const Tuple &args );
79 typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws );
80
81 MethodDefExt
82 (
83 const char *_name,
84 method_varargs_function_t _function,
85 method_varargs_call_handler_t _handler,
86 const char *_doc
87 )
88 {
89 ext_meth_def.ml_name = const_cast<char *>(_name);
90 ext_meth_def.ml_meth = _handler;
91 ext_meth_def.ml_flags = METH_VARARGS;
92 ext_meth_def.ml_doc = const_cast<char *>(_doc);
93
94 ext_varargs_function = _function;
95 ext_keyword_function = NULL;
96 }
97
98 MethodDefExt
99 (
100 const char *_name,
101 method_keyword_function_t _function,
102 method_keyword_call_handler_t _handler,
103 const char *_doc
104 )
105 {
106 ext_meth_def.ml_name = const_cast<char *>(_name);
107 ext_meth_def.ml_meth = method_varargs_call_handler_t( _handler );
108 ext_meth_def.ml_flags = METH_VARARGS|METH_KEYWORDS;
109 ext_meth_def.ml_doc = const_cast<char *>(_doc);
110
111 ext_varargs_function = NULL;
112 ext_keyword_function = _function;
113 }
114
115 ~MethodDefExt()
116 {}
117
118 PyMethodDef ext_meth_def;
119 method_varargs_function_t ext_varargs_function;
120 method_keyword_function_t ext_keyword_function;
121 };
122
123 class ExtensionModuleBase
124 {
125 public:
126 ExtensionModuleBase( const char *name );
127 virtual ~ExtensionModuleBase();
128
129 Module module(void) const; // only valid after initialize() has been called
130 Dict moduleDictionary(void) const; // only valid after initialize() has been called
131
132 virtual Object invoke_method_keyword( const std::string &_name, const Tuple &_args, const Dict &_keywords ) = 0;
133 virtual Object invoke_method_varargs( const std::string &_name, const Tuple &_args ) = 0;
134
135 const std::string &name() const;
136 const std::string &fullName() const;
137
138 protected:
139 // Initialize the module
140 void initialize( const char *module_doc );
141
142 const std::string module_name;
143 const std::string full_module_name;
144 MethodTable method_table;
145
146 private:
147
148 //
149 // prevent the compiler generating these unwanted functions
150 //
151 ExtensionModuleBase( const ExtensionModuleBase & ); //unimplemented
152 void operator=( const ExtensionModuleBase & ); //unimplemented
153
154 };
155
156 extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords );
157 extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args );
158 extern "C" void do_not_dealloc( void * );
159
160
161 template<typename T>
162 class ExtensionModule : public ExtensionModuleBase
163 {
164 public:
165 ExtensionModule( const char *name )
166 : ExtensionModuleBase( name )
167 {}
168 virtual ~ExtensionModule()
169 {}
170
171 protected:
172 typedef Object (T::*method_varargs_function_t)( const Tuple &args );
173 typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws );
174 typedef std::map<std::string,MethodDefExt<T> *> method_map_t;
175
176 static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" )
177 {
178 method_map_t &mm = methods();
179
180 MethodDefExt<T> *method_definition = new MethodDefExt<T>
181 (
182 name,
183 function,
184 method_varargs_call_handler,
185 doc
186 );
187
188 mm[std::string( name )] = method_definition;
189 }
190
191 static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" )
192 {
193 method_map_t &mm = methods();
194
195 MethodDefExt<T> *method_definition = new MethodDefExt<T>
196 (
197 name,
198 function,
199 method_keyword_call_handler,
200 doc
201 );
202
203 mm[std::string( name )] = method_definition;
204 }
205
206 void initialize( const char *module_doc="" )
207 {
208 ExtensionModuleBase::initialize( module_doc );
209 Dict dict( moduleDictionary() );
210
211 //
212 // put each of the methods into the modules dictionary
213 // so that we get called back at the function in T.
214 //
215 method_map_t &mm = methods();
216 typename method_map_t::iterator i;
217
218 for( i=mm.begin(); i != mm.end(); ++i )
219 {
220 MethodDefExt<T> *method_definition = (*i).second;
221
222 static PyObject *self = PyCObject_FromVoidPtr( this, do_not_dealloc );
223
224 Tuple args( 2 );
225 args[0] = Object( self );
226 args[1] = String( (*i).first );
227
228 PyObject *func = PyCFunction_New
229 (
230 &method_definition->ext_meth_def,
231 new_reference_to( args )
232 );
233
234 dict[ (*i).first ] = Object( func );
235 }
236 }
237
238 protected: // Tom Malcolmson reports that derived classes need access to these
239
240 static method_map_t &methods(void)
241 {
242 static method_map_t *map_of_methods = NULL;
243 if( map_of_methods == NULL )
244 map_of_methods = new method_map_t;
245
246 return *map_of_methods;
247 }
248
249
250 // this invoke function must be called from within a try catch block
251 virtual Object invoke_method_keyword( const std::string &name, const Tuple &args, const Dict &keywords )
252 {
253 method_map_t &mm = methods();
254 MethodDefExt<T> *meth_def = mm[ name ];
255 if( meth_def == NULL )
256 {
257 std::string error_msg( "CXX - cannot invoke keyword method named " );
258 error_msg += name;
259 throw RuntimeError( error_msg );
260 }
261
262 // cast up to the derived class
263 T *self = static_cast<T *>(this);
264
265 return (self->*meth_def->ext_keyword_function)( args, keywords );
266 }
267
268 // this invoke function must be called from within a try catch block
269 virtual Object invoke_method_varargs( const std::string &name, const Tuple &args )
270 {
271 method_map_t &mm = methods();
272 MethodDefExt<T> *meth_def = mm[ name ];
273 if( meth_def == NULL )
274 {
275 std::string error_msg( "CXX - cannot invoke varargs method named " );
276 error_msg += name;
277 throw RuntimeError( error_msg );
278 }
279
280 // cast up to the derived class
281 T *self = static_cast<T *>(this);
282
283 return (self->*meth_def->ext_varargs_function)( args );
284 }
285
286 private:
287 //
288 // prevent the compiler generating these unwanted functions
289 //
290 ExtensionModule( const ExtensionModule<T> & ); //unimplemented
291 void operator=( const ExtensionModule<T> & ); //unimplemented
292 };
293
294
295 class PythonType
296 {
297 public:
298 // if you define one sequence method you must define
299 // all of them except the assigns
300
301 PythonType (size_t base_size, int itemsize, const char *default_name );
302 virtual ~PythonType ();
303
304 const char *getName () const;
305 const char *getDoc () const;
306
307 PyTypeObject* type_object () const;
308 void name (const char* nam);
309 void doc (const char* d);
310 void dealloc(void (*f)(PyObject*));
311
312 void supportPrint(void);
313 void supportGetattr(void);
314 void supportSetattr(void);
315 void supportGetattro(void);
316 void supportSetattro(void);
317 void supportCompare(void);
318 void supportRepr(void);
319 void supportStr(void);
320 void supportHash(void);
321 void supportCall(void);
322
323 void supportSequenceType(void);
324 void supportMappingType(void);
325 void supportNumberType(void);
326 void supportBufferType(void);
327
328 protected:
329 PyTypeObject *table;
330 PySequenceMethods *sequence_table;
331 PyMappingMethods *mapping_table;
332 PyNumberMethods *number_table;
333 PyBufferProcs *buffer_table;
334
335 void init_sequence();
336 void init_mapping();
337 void init_number();
338 void init_buffer();
339
340 private:
341 //
342 // prevent the compiler generating these unwanted functions
343 //
344 PythonType (const PythonType& tb); // unimplemented
345 void operator=(const PythonType& t); // unimplemented
346
347 }; // end of PythonType
348
349
350
351 // Class PythonExtension is what you inherit from to create
352 // a new Python extension type. You give your class itself
353 // as the template paramter.
354
355 // There are two ways that extension objects can get destroyed.
356 // 1. Their reference count goes to zero
357 // 2. Someone does an explicit delete on a pointer.
358 // In (1) the problem is to get the destructor called
359 // We register a special deallocator in the Python type object
360 // (see behaviors()) to do this.
361 // In (2) there is no problem, the dtor gets called.
362
363 // PythonExtension does not use the usual Python heap allocator,
364 // instead using new/delete. We do the setting of the type object
365 // and reference count, usually done by PyObject_New, in the
366 // base class ctor.
367
368 // This special deallocator does a delete on the pointer.
369
370
371 class PythonExtensionBase : public PyObject
372 {
373 public:
374 PythonExtensionBase();
375 virtual ~PythonExtensionBase();
376
377 public:
378 virtual int print( FILE *, int );
379 virtual Object getattr( const char * ) = 0;
380 virtual int setattr( const char *, const Object & );
381 virtual Object getattro( const Object & );
382 virtual int setattro( const Object &, const Object & );
383 virtual int compare( const Object & );
384 virtual Object repr();
385 virtual Object str();
386 virtual long hash();
387 virtual Object call( const Object &, const Object & );
388
389 // Sequence methods
390 virtual int sequence_length();
391 virtual Object sequence_concat( const Object & );
392 virtual Object sequence_repeat( int );
393 virtual Object sequence_item( int );
394 virtual Object sequence_slice( int, int );
395 virtual int sequence_ass_item( int, const Object & );
396 virtual int sequence_ass_slice( int, int, const Object & );
397
398 // Mapping
399 virtual int mapping_length();
400 virtual Object mapping_subscript( const Object & );
401 virtual int mapping_ass_subscript( const Object &, const Object & );
402
403 // Number
404 virtual int number_nonzero();
405 virtual Object number_negative();
406 virtual Object number_positive();
407 virtual Object number_absolute();
408 virtual Object number_invert();
409 virtual Object number_int();
410 virtual Object number_float();
411 virtual Object number_long();
412 virtual Object number_oct();
413 virtual Object number_hex();
414 virtual Object number_add( const Object & );
415 virtual Object number_subtract( const Object & );
416 virtual Object number_multiply( const Object & );
417 virtual Object number_divide( const Object & );
418 virtual Object number_remainder( const Object & );
419 virtual Object number_divmod( const Object & );
420 virtual Object number_lshift( const Object & );
421 virtual Object number_rshift( const Object & );
422 virtual Object number_and( const Object & );
423 virtual Object number_xor( const Object & );
424 virtual Object number_or( const Object & );
425 virtual Object number_power( const Object &, const Object & );
426
427 // Buffer
428 virtual int buffer_getreadbuffer( int, void** );
429 virtual int buffer_getwritebuffer( int, void** );
430 virtual int buffer_getsegcount( int* );
431
432 private:
433 void missing_method( void );
434 static PyObject *method_call_handler( PyObject *self, PyObject *args );
435 };
436
437 template<typename T>
438 class PythonExtension: public PythonExtensionBase
439 {
440 public:
441 static PyTypeObject* type_object()
442 {
443 return behaviors().type_object();
444 }
445
446 static int check( PyObject *p )
447 {
448 // is p like me?
449 return p->ob_type == type_object();
450 }
451
452 static int check( const Object& ob )
453 {
454 return check( ob.ptr());
455 }
456
457
458 //
459 // every object needs getattr implemented
460 // to support methods
461 //
462 virtual Object getattr( const char *name )
463 {
464 return getattr_methods( name );
465 }
466
467 protected:
468 explicit PythonExtension()
469 : PythonExtensionBase()
470 {
471 #ifdef PyObject_INIT
472 (void)PyObject_INIT( this, type_object() );
473 #else
474 ob_refcnt = 1;
475 ob_type = type_object();
476 #endif
477
478 // every object must support getattr
479 behaviors().supportGetattr();
480 }
481
482 virtual ~PythonExtension()
483 {}
484
485 static PythonType &behaviors()
486 {
487 static PythonType* p;
488 if( p == NULL )
489 {
490#if defined( _CPPRTTI )
491 const char *default_name = (typeid ( T )).name();
492#else
493 const char *default_name = "unknown";
494#endif
495 p = new PythonType( sizeof( T ), 0, default_name );
496 p->dealloc( extension_object_deallocator );
497 }
498
499 return *p;
500 }
501
502
503 typedef Object (T::*method_varargs_function_t)( const Tuple &args );
504 typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws );
505 typedef std::map<std::string,MethodDefExt<T> *> method_map_t;
506
507 // support the default attributes, __name__, __doc__ and methods
508 virtual Object getattr_default( const char *_name )
509 {
510 std::string name( _name );
511
512 if( name == "__name__" && type_object()->tp_name != NULL )
513 {
514 return Py::String( type_object()->tp_name );
515 }
516 else if( name == "__doc__" && type_object()->tp_doc != NULL )
517 {
518 return Py::String( type_object()->tp_doc );
519 }
520
521// trying to fake out being a class for help()
522// else if( name == "__bases__" )
523// {
524// return Py::Tuple(0);
525// }
526// else if( name == "__module__" )
527// {
528// return Py::Nothing();
529// }
530// else if( name == "__dict__" )
531// {
532// return Py::Dict();
533// }
534 else
535 {
536 return getattr_methods( _name );
537 }
538 }
539
540 // turn a name into function object
541 virtual Object getattr_methods( const char *_name )
542 {
543 std::string name( _name );
544
545 method_map_t &mm = methods();
546
547 if( name == "__methods__" )
548 {
549 List methods;
550
551 for( typename method_map_t::iterator i = mm.begin(); i != mm.end(); ++i )
552 methods.append( String( (*i).first ) );
553
554 return methods;
555 }
556
557 // see if name exists
558 if( mm.find( name ) == mm.end() )
559 throw AttributeError( "method '" + name + "' does not exist." );
560
561 Tuple self( 2 );
562
563 self[0] = Object( this );
564 self[1] = String( name );
565
566 MethodDefExt<T> *method_definition = mm[ name ];
567
568 PyObject *func = PyCFunction_New( &method_definition->ext_meth_def, self.ptr() );
569
570 return Object(func, true);
571 }
572
573 static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" )
574 {
575 method_map_t &mm = methods();
576
577 MethodDefExt<T> *method_definition = new MethodDefExt<T>
578 (
579 name,
580 function,
581 method_varargs_call_handler,
582 doc
583 );
584
585 mm[std::string( name )] = method_definition;
586 }
587
588 static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" )
589 {
590 method_map_t &mm = methods();
591
592 MethodDefExt<T> *method_definition = new MethodDefExt<T>
593 (
594 name,
595 function,
596 method_keyword_call_handler,
597 doc
598 );
599
600 mm[std::string( name )] = method_definition;
601 }
602
603 private:
604 static method_map_t &methods(void)
605 {
606 static method_map_t *map_of_methods = NULL;
607 if( map_of_methods == NULL )
608 map_of_methods = new method_map_t;
609
610 return *map_of_methods;
611 }
612
613 static PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords )
614 {
615 try
616 {
617 Tuple self_and_name_tuple( _self_and_name_tuple );
618
619 PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
620 T *self = static_cast<T *>( self_in_cobject );
621
622 String name( self_and_name_tuple[1] );
623
624 method_map_t &mm = methods();
625 MethodDefExt<T> *meth_def = mm[ name ];
626 if( meth_def == NULL )
627 return 0;
628
629 Tuple args( _args );
630
631 // _keywords may be NULL so be careful about the way the dict is created
632 Dict keywords;
633 if( _keywords != NULL )
634 keywords = Dict( _keywords );
635
636 Object result( (self->*meth_def->ext_keyword_function)( args, keywords ) );
637
638 return new_reference_to( result.ptr() );
639 }
640 catch( Exception & )
641 {
642 return 0;
643 }
644 }
645
646 static PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args )
647 {
648 try
649 {
650 Tuple self_and_name_tuple( _self_and_name_tuple );
651
652 PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
653 T *self = static_cast<T *>( self_in_cobject );
654
655 String name( self_and_name_tuple[1] );
656
657 method_map_t &mm = methods();
658 MethodDefExt<T> *meth_def = mm[ name ];
659 if( meth_def == NULL )
660 return 0;
661
662 Tuple args( _args );
663
664 Object result;
665
666 // TMM: 7Jun'01 - Adding try & catch in case of STL debug-mode exceptions.
667 #ifdef _STLP_DEBUG
668 try
669 {
670 result = (self->*meth_def->ext_varargs_function)( args );
671 }
672 catch (std::__stl_debug_exception)
673 {
674 // throw cxx::RuntimeError( sErrMsg );
675 throw cxx::RuntimeError( "Error message not set yet." );
676 }
677 #else
678 result = (self->*meth_def->ext_varargs_function)( args );
679 #endif // _STLP_DEBUG
680
681 return new_reference_to( result.ptr() );
682 }
683 catch( Exception & )
684 {
685 return 0;
686 }
687 }
688
689 static void extension_object_deallocator ( PyObject* t )
690 {
691 delete (T *)( t );
692 }
693
694 //
695 // prevent the compiler generating these unwanted functions
696 //
697 explicit PythonExtension( const PythonExtension<T>& other );
698 void operator=( const PythonExtension<T>& rhs );
699 };
700
701 //
702 // ExtensionObject<T> is an Object that will accept only T's.
703 //
704 template<typename T>
705 class ExtensionObject: public Object
706 {
707 public:
708
709 explicit ExtensionObject ( PyObject *pyob )
710 : Object( pyob )
711 {
712 validate();
713 }
714
715 ExtensionObject( const ExtensionObject<T>& other )
716 : Object( *other )
717 {
718 validate();
719 }
720
721 ExtensionObject( const Object& other )
722 : Object( *other )
723 {
724 validate();
725 }
726
727 ExtensionObject& operator= ( const Object& rhs )
728 {
729 return (*this = *rhs );
730 }
731
732 ExtensionObject& operator= ( PyObject* rhsp )
733 {
734 if( ptr() == rhsp )
735 return *this;
736 set( rhsp );
737 return *this;
738 }
739
740 virtual bool accepts ( PyObject *pyob ) const
741 {
742 return ( pyob && T::check( pyob ));
743 }
744
745 //
746 // Obtain a pointer to the PythonExtension object
747 //
748 T *extensionObject(void)
749 {
750 return static_cast<T *>( ptr() );
751 }
752 };
753
754 } // Namespace Py
755// End of CXX_Extensions.h
756#endif
TDEAction * print(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
const char * name(StdAction id)
@ String
string
Definition property.h:71
@ List
TQValueList<TQVariant>
Definition property.h:70