PageRenderTime 27ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/external/pycxx/CXX/ExtensionModule.hxx

https://github.com/worldforge/cyphesis
C++ Header | 206 lines | 117 code | 33 blank | 56 comment | 5 complexity | 2eda13c6c050deb189801a6d6584dc6a MD5 | raw file
  1. //-----------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1998 - 2007, The Regents of the University of California
  4. // Produced at the Lawrence Livermore National Laboratory
  5. // All rights reserved.
  6. //
  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.
  10. //
  11. // Redistribution and use in source and binary forms, with or without
  12. // modification, are permitted provided that the following conditions are met:
  13. //
  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.
  22. //
  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
  34. // DAMAGE.
  35. //
  36. //-----------------------------------------------------------------------------
  37. #ifndef __CXX_ExtensionModule__h
  38. #define __CXX_ExtensionModule__h
  39. namespace Py
  40. {
  41. class ExtensionModuleBase
  42. {
  43. public:
  44. ExtensionModuleBase( const char *name );
  45. virtual ~ExtensionModuleBase();
  46. Module module( void ) const; // only valid after initialize() has been called
  47. Dict moduleDictionary( void ) const; // only valid after initialize() has been called
  48. virtual Object invoke_method_noargs( void *method_def ) = 0;
  49. virtual Object invoke_method_keyword( void *method_def, const Tuple &_args, const Dict &_keywords ) = 0;
  50. virtual Object invoke_method_varargs( void *method_def, const Tuple &_args ) = 0;
  51. const std::string &name() const;
  52. const std::string &fullName() const;
  53. // what is returned from PyInit_<module> function
  54. Object moduleObject( void ) const;
  55. protected:
  56. // Initialize the module
  57. void initialize( const char *module_doc );
  58. const std::string m_module_name;
  59. const std::string m_full_module_name;
  60. MethodTable m_method_table;
  61. PyModuleDef m_module_def;
  62. PyObject *m_module;
  63. private:
  64. //
  65. // prevent the compiler generating these unwanted functions
  66. //
  67. ExtensionModuleBase( const ExtensionModuleBase & ); //unimplemented
  68. void operator=( const ExtensionModuleBase & ); //unimplemented
  69. };
  70. // Note: Python calls noargs as varargs buts args==nullptr
  71. extern "C" PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * );
  72. extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args );
  73. extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords );
  74. template<TEMPLATE_TYPENAME T>
  75. class ExtensionModule : public ExtensionModuleBase
  76. {
  77. public:
  78. ExtensionModule( const char *name )
  79. : ExtensionModuleBase( name )
  80. {}
  81. virtual ~ExtensionModule()
  82. {}
  83. protected:
  84. typedef Object (T::*method_noargs_function_t)();
  85. typedef Object (T::*method_varargs_function_t)( const Tuple &args );
  86. typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws );
  87. typedef std::map<std::string, MethodDefExt<T> *> method_map_t;
  88. static void add_noargs_method( const char *name, method_noargs_function_t function, const char *doc="" )
  89. {
  90. method_map_t &mm = methods();
  91. mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_noargs_call_handler, doc );
  92. }
  93. static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" )
  94. {
  95. method_map_t &mm = methods();
  96. mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_varargs_call_handler, doc );
  97. }
  98. static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" )
  99. {
  100. method_map_t &mm = methods();
  101. mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_keyword_call_handler, doc );
  102. }
  103. void initialize( const char *module_doc="" )
  104. {
  105. ExtensionModuleBase::initialize( module_doc );
  106. Dict dict( moduleDictionary() );
  107. //
  108. // put each of the methods into the modules dictionary
  109. // so that we get called back at the function in T.
  110. //
  111. method_map_t &mm = methods();
  112. EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.begin();
  113. EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end();
  114. for ( ; i != i_end; ++i )
  115. {
  116. MethodDefExt<T> *method_def = (*i).second;
  117. static PyObject *self = PyCapsule_New( this, nullptr, nullptr );
  118. Tuple args( 2 );
  119. args[0] = Object( self, true );
  120. args[1] = Object( PyCapsule_New( method_def, nullptr, nullptr ), true );
  121. assert( m_module != nullptr );
  122. PyObject *func = PyCFunction_NewEx
  123. (
  124. &method_def->ext_meth_def,
  125. new_reference_to( args ),
  126. m_module
  127. );
  128. method_def->py_method = Object( func, true );
  129. dict[ (*i).first ] = method_def->py_method;
  130. }
  131. }
  132. protected: // Tom Malcolmson reports that derived classes need access to these
  133. static method_map_t &methods( void )
  134. {
  135. static method_map_t *map_of_methods = nullptr;
  136. if( map_of_methods == nullptr )
  137. map_of_methods = new method_map_t;
  138. return *map_of_methods;
  139. }
  140. // this invoke function must be called from within a try catch block
  141. virtual Object invoke_method_noargs( void *method_def )
  142. {
  143. // cast up to the derived class, method_def and call
  144. T *self = static_cast<T *>( this );
  145. MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def );
  146. return (self->*meth_def->ext_noargs_function)();
  147. }
  148. // this invoke function must be called from within a try catch block
  149. virtual Object invoke_method_varargs( void *method_def, const Tuple &args )
  150. {
  151. // cast up to the derived class, method_def and call
  152. T *self = static_cast<T *>( this );
  153. MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def );
  154. return (self->*meth_def->ext_varargs_function)( args );
  155. }
  156. // this invoke function must be called from within a try catch block
  157. virtual Object invoke_method_keyword( void *method_def, const Tuple &args, const Dict &keywords )
  158. {
  159. // cast up to the derived class, method_def and call
  160. T *self = static_cast<T *>( this );
  161. MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def );
  162. return (self->*meth_def->ext_keyword_function)( args, keywords );
  163. }
  164. private:
  165. //
  166. // prevent the compiler generating these unwanted functions
  167. //
  168. ExtensionModule( const ExtensionModule<T> & ); //unimplemented
  169. void operator=( const ExtensionModule<T> & ); //unimplemented
  170. };
  171. } // Namespace Py
  172. // End of __CXX_ExtensionModule__h
  173. #endif