ExtensionModule.hxx

Go to the documentation of this file.
00001 //-----------------------------------------------------------------------------
00002 //
00003 // Copyright (c) 1998 - 2007, The Regents of the University of California
00004 // Produced at the Lawrence Livermore National Laboratory
00005 // All rights reserved.
00006 //
00007 // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The
00008 // full copyright notice is contained in the file COPYRIGHT located at the root
00009 // of the PyCXX distribution.
00010 //
00011 // Redistribution  and  use  in  source  and  binary  forms,  with  or  without
00012 // modification, are permitted provided that the following conditions are met:
00013 //
00014 //  - Redistributions of  source code must  retain the above  copyright notice,
00015 //    this list of conditions and the disclaimer below.
00016 //  - Redistributions in binary form must reproduce the above copyright notice,
00017 //    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
00018 //    documentation and/or materials provided with the distribution.
00019 //  - Neither the name of the UC/LLNL nor  the names of its contributors may be
00020 //    used to  endorse or  promote products derived from  this software without
00021 //    specific prior written permission.
00022 //
00023 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
00024 // AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
00025 // IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
00026 // ARE  DISCLAIMED.  IN  NO  EVENT  SHALL  THE  REGENTS  OF  THE  UNIVERSITY OF
00027 // CALIFORNIA, THE U.S.  DEPARTMENT  OF  ENERGY OR CONTRIBUTORS BE  LIABLE  FOR
00028 // ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR CONSEQUENTIAL
00029 // DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
00030 // SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
00031 // CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
00032 // LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
00033 // OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00034 // DAMAGE.
00035 //
00036 //-----------------------------------------------------------------------------
00037 
00038 #ifndef __CXX_ExtensionModule__h
00039 #define __CXX_ExtensionModule__h
00040 
00041 namespace Py
00042 {
00043     class PYCXX_EXPORT ExtensionModuleBase
00044     {
00045     public:
00046         ExtensionModuleBase( const char *name );
00047         virtual ~ExtensionModuleBase();
00048 
00049         Module module( void ) const;            // only valid after initialize() has been called
00050         Dict moduleDictionary( void ) const;    // only valid after initialize() has been called
00051 
00052         virtual Object invoke_method_noargs( void *method_def ) = 0;
00053         virtual Object invoke_method_keyword( void *method_def, const Tuple &_args, const Dict &_keywords ) = 0;
00054         virtual Object invoke_method_varargs( void *method_def, const Tuple &_args ) = 0;
00055 
00056         const std::string &name() const;
00057         const std::string &fullName() const;
00058 
00059         // what is returned from PyInit_<module> function
00060         Object moduleObject( void ) const;
00061 
00062     protected:
00063         // Initialize the module
00064         void initialize( const char *module_doc );
00065 
00066         const std::string m_module_name;
00067         const std::string m_full_module_name;
00068         MethodTable m_method_table;
00069 #if PY3
00070         PyModuleDef m_module_def;
00071 #endif
00072         PyObject *m_module;
00073 
00074     private:
00075         //
00076         // prevent the compiler generating these unwanted functions
00077         //
00078         ExtensionModuleBase( const ExtensionModuleBase & );     //unimplemented
00079         void operator=( const ExtensionModuleBase & );          //unimplemented
00080     };
00081 
00082     // Note: Python calls noargs as varargs buts args==NULL
00083     extern "C" PYCXX_EXPORT PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * );
00084     extern "C" PYCXX_EXPORT PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args );
00085     extern "C" PYCXX_EXPORT PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords );
00086 
00087     extern "C" PYCXX_EXPORT void do_not_dealloc( void * );
00088 
00089     template<TEMPLATE_TYPENAME T>
00090     class ExtensionModule : public ExtensionModuleBase
00091     {
00092     public:
00093         ExtensionModule( const char *name )
00094         : ExtensionModuleBase( name )
00095         {}
00096         virtual ~ExtensionModule()
00097         {}
00098 
00099     protected:
00100         typedef Object (T::*method_noargs_function_t)();
00101         typedef Object (T::*method_varargs_function_t)( const Tuple &args );
00102         typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws );
00103         typedef std::map<std::string, MethodDefExt<T> *> method_map_t;
00104 
00105         static void add_noargs_method( const char *name, method_noargs_function_t function, const char *doc="" )
00106         {
00107             method_map_t &mm = methods();
00108             mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_noargs_call_handler, doc );
00109         }
00110 
00111         static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" )
00112         {
00113             method_map_t &mm = methods();
00114             mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_varargs_call_handler, doc );
00115         }
00116 
00117         static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" )
00118         {
00119             method_map_t &mm = methods();
00120             mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_keyword_call_handler, doc );
00121         }
00122 
00123         void initialize( const char *module_doc="" )
00124         {
00125             ExtensionModuleBase::initialize( module_doc );
00126             Dict dict( moduleDictionary() );
00127 
00128             //
00129             // put each of the methods into the modules dictionary
00130             // so that we get called back at the function in T.
00131             //
00132             method_map_t &mm = methods();
00133             EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.begin();
00134             EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end();
00135             for ( ; i != i_end; ++i )
00136             {
00137                 MethodDefExt<T> *method_def = (*i).second;
00138 
00139                 static PyObject *self = PyCObject_FromVoidPtr( this, do_not_dealloc );
00140 
00141                 Tuple args( 2 );
00142                 args[0] = Object( self );
00143                 args[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ) );
00144 
00145                 PyObject *func = PyCFunction_New
00146                                     (
00147                                     &method_def->ext_meth_def,
00148                                     new_reference_to( args )
00149                                     );
00150 
00151                 method_def->py_method = Object( func, true );
00152 
00153                 dict[ (*i).first ] = method_def->py_method;
00154             }
00155         }
00156 
00157     protected:    // Tom Malcolmson reports that derived classes need access to these
00158         static method_map_t &methods( void )
00159         {
00160             static method_map_t *map_of_methods = NULL;
00161             if( map_of_methods == NULL )
00162                 map_of_methods = new method_map_t;
00163 
00164             return *map_of_methods;
00165         }
00166 
00167         // this invoke function must be called from within a try catch block
00168         virtual Object invoke_method_noargs( void *method_def )
00169         {
00170             // cast up to the derived class, method_def and call
00171             T *self = static_cast<T *>( this );
00172             MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def );
00173 
00174             return (self->*meth_def->ext_noargs_function)();
00175         }
00176 
00177         // this invoke function must be called from within a try catch block
00178         virtual Object invoke_method_varargs( void *method_def, const Tuple &args )
00179         {
00180             // cast up to the derived class, method_def and call
00181             T *self = static_cast<T *>( this );
00182             MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def );
00183 
00184             return (self->*meth_def->ext_varargs_function)( args );
00185         }
00186 
00187         // this invoke function must be called from within a try catch block
00188         virtual Object invoke_method_keyword( void *method_def, const Tuple &args, const Dict &keywords )
00189         {
00190             // cast up to the derived class, method_def and call
00191             T *self = static_cast<T *>( this );
00192             MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def );
00193 
00194             return (self->*meth_def->ext_keyword_function)( args, keywords );
00195         }
00196 
00197     private:
00198         //
00199         // prevent the compiler generating these unwanted functions
00200         //
00201         ExtensionModule( const ExtensionModule<T> & );  //unimplemented
00202         void operator=( const ExtensionModule<T> & );   //unimplemented
00203     };
00204 } // Namespace Py
00205 
00206 
00207 // End of __CXX_ExtensionModule__h
00208 #endif

Generated on Wed Nov 23 19:00:10 2011 for FreeCAD by  doxygen 1.6.1