1 //-----------------------------------------------------------------------------
3 // Copyright (c) 1998 - 2007, The Regents of the University of California
4 // Produced at the Lawrence Livermore National Laboratory
5 // All rights reserved.
7 // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The
8 // full copyright notice is contained in the file COPYRIGHT located at the root
9 // of the PyCXX distribution.
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are met:
14 // - Redistributions of source code must retain the above copyright notice,
15 // this list of conditions and the disclaimer below.
16 // - Redistributions in binary form must reproduce the above copyright notice,
17 // this list of conditions and the disclaimer (as noted below) in the
18 // documentation and/or materials provided with the distribution.
19 // - Neither the name of the UC/LLNL nor the names of its contributors may be
20 // used to endorse or promote products derived from this software without
21 // specific prior written permission.
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF
27 // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR
28 // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
36 //-----------------------------------------------------------------------------
38 #ifndef __CXX_ExtensionModule__h
39 #define __CXX_ExtensionModule__h
43 class ExtensionModuleBase
46 ExtensionModuleBase( const char *name
);
47 virtual ~ExtensionModuleBase();
49 Module
module( void ) const; // only valid after initialize() has been called
50 Dict
moduleDictionary( void ) const; // only valid after initialize() has been called
52 virtual Object
invoke_method_noargs( void *method_def
) = 0;
53 virtual Object
invoke_method_keyword( void *method_def
, const Tuple
&_args
, const Dict
&_keywords
) = 0;
54 virtual Object
invoke_method_varargs( void *method_def
, const Tuple
&_args
) = 0;
56 const std::string
&name() const;
57 const std::string
&fullName() const;
59 // what is returned from PyInit_<module> function
60 Object
moduleObject( void ) const;
63 // Initialize the module
64 void initialize( const char *module_doc
);
66 const std::string m_module_name
;
67 const std::string m_full_module_name
;
68 MethodTable m_method_table
;
69 PyModuleDef m_module_def
;
74 // prevent the compiler generating these unwanted functions
76 ExtensionModuleBase( const ExtensionModuleBase
& ); //unimplemented
77 void operator=( const ExtensionModuleBase
& ); //unimplemented
80 // Note: Python calls noargs as varargs buts args==NULL
81 extern "C" PyObject
*method_noargs_call_handler( PyObject
*_self_and_name_tuple
, PyObject
* );
82 extern "C" PyObject
*method_varargs_call_handler( PyObject
*_self_and_name_tuple
, PyObject
*_args
);
83 extern "C" PyObject
*method_keyword_call_handler( PyObject
*_self_and_name_tuple
, PyObject
*_args
, PyObject
*_keywords
);
85 extern "C" void do_not_dealloc( void * );
87 template<TEMPLATE_TYPENAME T
>
88 class ExtensionModule
: public ExtensionModuleBase
91 ExtensionModule( const char *name
)
92 : ExtensionModuleBase( name
)
94 virtual ~ExtensionModule()
98 typedef Object (T::*method_noargs_function_t
)();
99 typedef Object (T::*method_varargs_function_t
)( const Tuple
&args
);
100 typedef Object (T::*method_keyword_function_t
)( const Tuple
&args
, const Dict
&kws
);
101 typedef std::map
<std::string
, MethodDefExt
<T
> *> method_map_t
;
103 static void add_noargs_method( const char *name
, method_noargs_function_t function
, const char *doc
="" )
105 method_map_t
&mm
= methods();
106 mm
[ std::string( name
) ] = new MethodDefExt
<T
>( name
, function
, method_noargs_call_handler
, doc
);
109 static void add_varargs_method( const char *name
, method_varargs_function_t function
, const char *doc
="" )
111 method_map_t
&mm
= methods();
112 mm
[ std::string( name
) ] = new MethodDefExt
<T
>( name
, function
, method_varargs_call_handler
, doc
);
115 static void add_keyword_method( const char *name
, method_keyword_function_t function
, const char *doc
="" )
117 method_map_t
&mm
= methods();
118 mm
[ std::string( name
) ] = new MethodDefExt
<T
>( name
, function
, method_keyword_call_handler
, doc
);
121 void initialize( const char *module_doc
="" )
123 ExtensionModuleBase::initialize( module_doc
);
124 Dict
dict( moduleDictionary() );
127 // put each of the methods into the modules dictionary
128 // so that we get called back at the function in T.
130 method_map_t
&mm
= methods();
131 EXPLICIT_TYPENAME
method_map_t::const_iterator i
= mm
.begin();
132 EXPLICIT_TYPENAME
method_map_t::const_iterator i_end
= mm
.end();
133 for ( ; i
!= i_end
; ++i
)
135 MethodDefExt
<T
> *method_def
= (*i
).second
;
137 static PyObject
*self
= PyCObject_FromVoidPtr( this, do_not_dealloc
);
140 args
[0] = Object( self
);
141 args
[1] = Object( PyCObject_FromVoidPtr( method_def
, do_not_dealloc
) );
143 PyObject
*func
= PyCFunction_New
145 &method_def
->ext_meth_def
,
146 new_reference_to( args
)
149 method_def
->py_method
= Object( func
, true );
151 dict
[ (*i
).first
] = method_def
->py_method
;
155 protected: // Tom Malcolmson reports that derived classes need access to these
156 static method_map_t
&methods( void )
158 static method_map_t
*map_of_methods
= NULL
;
159 if( map_of_methods
== NULL
)
160 map_of_methods
= new method_map_t
;
162 return *map_of_methods
;
165 // this invoke function must be called from within a try catch block
166 virtual Object
invoke_method_noargs( void *method_def
)
168 // cast up to the derived class, method_def and call
169 T
*self
= static_cast<T
*>( this );
170 MethodDefExt
<T
> *meth_def
= reinterpret_cast<MethodDefExt
<T
> *>( method_def
);
172 return (self
->*meth_def
->ext_noargs_function
)();
175 // this invoke function must be called from within a try catch block
176 virtual Object
invoke_method_varargs( void *method_def
, const Tuple
&args
)
178 // cast up to the derived class, method_def and call
179 T
*self
= static_cast<T
*>( this );
180 MethodDefExt
<T
> *meth_def
= reinterpret_cast<MethodDefExt
<T
> *>( method_def
);
182 return (self
->*meth_def
->ext_varargs_function
)( args
);
185 // this invoke function must be called from within a try catch block
186 virtual Object
invoke_method_keyword( void *method_def
, const Tuple
&args
, const Dict
&keywords
)
188 // cast up to the derived class, method_def and call
189 T
*self
= static_cast<T
*>( this );
190 MethodDefExt
<T
> *meth_def
= reinterpret_cast<MethodDefExt
<T
> *>( method_def
);
192 return (self
->*meth_def
->ext_keyword_function
)( args
, keywords
);
197 // prevent the compiler generating these unwanted functions
199 ExtensionModule( const ExtensionModule
<T
> & ); //unimplemented
200 void operator=( const ExtensionModule
<T
> & ); //unimplemented
205 // End of __CXX_ExtensionModule__h