QPy
Python-Qt dynamic bindings
|
00001 #pragma once 00002 // QPy - Copyright (c) 2012,2013 Ugo Varetto 00003 // All rights reserved. 00004 // 00005 // Redistribution and use in source and binary forms, with or without 00006 // modification, are permitted provided that the following conditions are met: 00007 // * Redistributions of source code must retain the above copyright 00008 // notice, this list of conditions and the following disclaimer. 00009 // * Redistributions in binary form must reproduce the above copyright 00010 // notice, this list of conditions and the following disclaimer in the 00011 // documentation and/or other materials provided with the distribution. 00012 // * Neither the name of the author and copyright holder nor the 00013 // names of contributors to the project may be used to endorse or promote products 00014 // derived from this software without specific prior written permission. 00015 // 00016 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00017 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 // DISCLAIMED. IN NO EVENT SHALL UGO VARETTO BE LIABLE FOR ANY 00020 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00022 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00023 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00025 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 00029 00030 #include <Python.h> 00031 #include <structmember.h> 00032 #include <stdexcept> 00033 #include <cassert> 00034 #include <iostream> 00035 #include <QObject> 00036 #include <QMetaObject> 00037 #include <QMetaMethod> 00038 #include <QList> 00039 #include <QString> 00040 #include <QSet> 00041 #include <string> 00042 #include <vector> 00043 #include <QDebug> 00044 #include "detail/PyDefaultArguments.h" 00045 #include "detail/PyArgWrappers.h" 00046 #include "detail/PyCallbackDispatcher.h" 00047 #include "detail/PyQVariantDefault.h" 00048 #include "PyMemberNameMapper.h" 00049 00050 00051 #define PY_CHECK( f ) {if( f != 0 ) throw std::runtime_error( "Python error" );} 00052 00053 namespace qpy { 00054 00056 inline void RaisePyError( const char* errMsg = 0, 00057 PyObject* errType = PyExc_Exception ) { 00058 PyErr_SetString( errType, errMsg ); 00059 } 00060 00065 00066 //------------------------------------------------------------------------------ 00074 class PyContext { 00075 typedef QList< QArgWrapper > QArgWrappers; 00076 typedef QList< QByteArray > ArgumentTypes; 00083 struct Method { 00084 //for overloading purposes: 00085 //QMap< int, tuple< QMetaMethod, QArgWrappers, PyArgWrapper> > 00086 //select the one matching the number of arguments 00087 QMetaMethod metaMethod_; 00088 QArgWrappers argumentWrappers_; 00089 PyArgWrapper returnWrapper_; 00090 const QMetaObject* metaObject_; 00091 Method( const QMetaMethod& mm, 00092 const QArgWrappers& pw, 00093 const PyArgWrapper& rw, 00094 const QMetaObject* mo ) : 00095 metaMethod_( mm ), argumentWrappers_( pw ), 00096 returnWrapper_( rw ), metaObject_( mo ) {} 00097 }; 00098 static const int MAX_GENERIC_ARGS = 10; 00099 public: 00100 typedef QList< Method > Methods; 00101 public: //must be public because type access might be needed 00102 //from PyArguments; declaring some PyArguments as friend 00103 //won't work when new argument constructors provided by 00104 //client code need to be registered 00110 struct Type { 00111 const QMetaObject* metaObject; 00112 //for overloading purposes: 00113 //QMap< int, QArgWrappers > 00114 //currently overloading is done through a run-time search 00115 QList< QArgWrappers > ctorParams; 00116 Methods methods; 00117 PyTypeObject pyType; 00118 //required to keep char* to be passed around 00119 std::vector< std::string > pyMethodNames; 00120 std::vector< PyGetSetDef > pyMembers; 00121 // need string to pass references to 00122 // contained c_str 00123 std::string fullClassName; 00124 std::string className; 00125 std::string doc; 00126 PyObject* pyModule; 00127 PyContext* pyContext; 00128 }; 00129 typedef QList< Type > Types; 00131 struct PyQObject { 00132 PyObject_HEAD 00133 char qobjectTag; 00134 QObject* obj; 00135 Type* type; 00136 PyObject* invoke; //method invocation function 00137 bool foreignOwned; 00138 PyObject* pyModule; 00139 }; 00140 public: 00142 PyContext() { 00143 InitArgFactory(); 00144 InitQVariantPyObjectMaps(); 00145 } 00148 ~PyContext() { 00149 for( QVariantToPyObjectMapType::iterator i = qvariantToPyObject_.begin(); 00150 i != qvariantToPyObject_.end(); ++i ) { 00151 if( !i.value()->ForeignOwned() ) delete i.value(); 00152 } 00153 for( PyObjectToQVariantMapType::iterator i = pyObjectToQVariant_.begin(); 00154 i != pyObjectToQVariant_.end(); ++i ) { 00155 if( !i.value()->ForeignOwned() ) delete i.value(); 00156 } 00157 } 00159 static const char* Version(); 00161 void AddGlobals( PyObject* module ) { 00162 PyModule_AddStringConstant( module, "__version__", Version() ); 00163 } 00178 PyTypeObject* AddType( const QMetaObject* mo, 00179 PyObject* module, 00180 bool checkConstructor = true, 00181 const QSet< QString >& selectedMembers = QSet< QString >(), 00182 const PyMemberNameMapper& mm = DefaultMemberNameMapper(), 00183 const char* className = 0, 00184 const char* doc = 0 ); 00196 template < typename T > void Add( PyObject* module, 00197 bool checkConstructor = true, 00198 const QSet< QString >& selectedMembers = QSet< QString >(), 00199 const PyMemberNameMapper& mm = DefaultMemberNameMapper(), 00200 const char* className = 0, 00201 const char* doc = 0 ) { 00202 AddType( &T::staticMetaObject, module, checkConstructor, selectedMembers, 00203 mm, className, doc ); 00204 } 00208 PyMethodDef* ModuleFunctions(); 00210 PyObject* AddObject( QObject* qobj, 00211 PyObject* targetModule, // where instance is added 00212 PyObject* typeModule, // where type is defined 00213 const char* instanceName, 00214 bool pythonOwned = false, 00215 const QSet< QString >& selectedMembers = QSet< QString >(), 00216 const PyMemberNameMapper& mm = DefaultMemberNameMapper() ); 00220 template < typename QArgConstructorT, typename PyArgConstructorT > 00221 bool RegisterType( const QString& typeName, bool overwrite = false ) { 00222 return RegisterType( typeName, new QArgConstructorT, new PyArgConstructorT, overwrite ); 00223 } 00224 template < typename QArgConstructorT, typename PyArgConstructorT > 00225 bool RegisterType( QMetaType::Type t, bool overwrite = false ) { 00226 return RegisterType( QMetaType::typeName( t ), 00227 new QArgConstructorT, new PyArgConstructorT, overwrite ); 00228 } 00232 template < typename T, typename QArgConstructorT, typename PyArgConstructorT > 00233 bool RegisterType( const QString& typeName, bool overwrite = false ) { 00234 return RegisterType( qRegisterMetaType< T >( typeName.toAscii().constData() ), 00235 new QArgConstructorT, new PyArgConstructorT, overwrite ); 00236 } 00237 void RegisterQVariantToPyObject( QVariant::Type t, QVariantToPyObject* qp ) { 00238 if( qvariantToPyObject_.contains( t ) ) { 00239 if( !qvariantToPyObject_[ t ]->ForeignOwned() ) delete qvariantToPyObject_[ t ]; 00240 } 00241 qvariantToPyObject_[ t ] = qp; 00242 } 00243 template < typename T > 00244 int RegisterQVariantToPyObject( QVariantToPyObject* qp ) { 00245 const int id = qRegisterMetaType< T >(); 00246 RegisterQVariantToPyObject( QVariant::Type( id ), qp ); 00247 return id; 00248 } 00249 void RegisterPyObjectToQVariant( QVariant::Type t, PyObjectToQVariant* qp ) { 00250 if( pyObjectToQVariant_.contains( t ) ) { 00251 if( !pyObjectToQVariant_[ t ]->ForeignOwned() ) delete pyObjectToQVariant_[ t ]; 00252 } 00253 pyObjectToQVariant_[ t ] = qp; 00254 } 00255 template < typename T > 00256 int RegisterPyObjectToQVariant( PyObjectToQVariant* qp ) { 00257 const int id = qRegisterMetaType< T >(); 00258 RegisterPyObjectToQVariant( qMetaTypeId< T >, qp ); 00259 return id; 00260 } 00261 void UnRegisterType( const QString& typeName ) { 00262 if( !argFactory_.contains( typeName ) ) return; 00263 argFactory_.erase( argFactory_.find( typeName ) ); 00264 } 00269 struct TypeConstruction { 00270 bool qtToPy; 00271 bool pyToQt; 00272 QString typeName; 00273 operator bool() const { return qtToPy || pyToQt; } 00274 TypeConstruction() : qtToPy( false ), pyToQt( false ) {} 00275 }; 00278 TypeConstruction RegTypeInfo( const QString& t ) const { 00279 TypeConstruction tc; 00280 if( !argFactory_.contains( t ) ) return tc; 00281 tc.pyToQt = dynamic_cast< const NoQArgConstructor* >( argFactory_[ t ].QArgCtor() ) == 0; 00282 tc.qtToPy = dynamic_cast< const NoPyArgConstructor* >( argFactory_[ t ].PyArgCtor() ) == 0; 00283 tc.typeName = t; 00284 return tc; 00285 } 00287 QList< TypeConstruction > RegisteredTypes() const { 00288 QList< TypeConstruction > tc; 00289 for( ArgFactory::const_iterator i = argFactory_.begin(); i != argFactory_.end(); ++i ) { 00290 tc.push_back( RegTypeInfo( i.key() ) ); 00291 } 00292 return tc; 00293 } 00294 private: 00296 void InitArgFactory(); 00298 void InitQVariantPyObjectMaps(); 00301 QArgWrappers GenerateQArgWrappers( const ArgumentTypes& at ); 00303 PyArgWrapper GeneratePyArgWrapper( QString typeName ); 00304 private: 00305 class ArgFactoryEntry { 00306 public: 00307 ArgFactoryEntry() : qac_( 0 ), pac_( 0 ) {} 00308 ArgFactoryEntry( const ArgFactoryEntry& fe ) 00309 : typeName_( fe.typeName_ ), qac_( 0 ), pac_( 0 ) { 00310 if( fe.qac_ ) qac_ = fe.qac_->Clone(); 00311 if( fe.pac_ ) pac_ = fe.pac_->Clone(); 00312 } 00313 ArgFactoryEntry( const QString& tn, QArgConstructor* qac, PyArgConstructor* pac ) 00314 : typeName_( tn ), qac_( qac ), pac_( pac ) {} 00315 const ArgFactoryEntry& operator=( const ArgFactoryEntry& fe ) { 00316 typeName_ = fe.typeName_; 00317 qac_ = fe.qac_ ? fe.qac_->Clone() : 0; 00318 pac_ = fe.pac_ ? fe.pac_->Clone() : 0; 00319 return *this; 00320 } 00321 ~ArgFactoryEntry() { 00322 delete qac_; 00323 delete pac_; 00324 } 00325 const QArgConstructor* QArgCtor() const { return qac_; } 00326 const PyArgConstructor* PyArgCtor() const { return pac_; } 00327 QArgConstructor* MakeQArgConstructor() const { return qac_->Clone(); } 00328 PyArgConstructor* MakePyArgConstructor() const { return pac_->Clone(); } 00329 const QString& TypeName() const { return typeName_; } 00330 private: 00331 QString typeName_; 00332 QArgConstructor* qac_; 00333 PyArgConstructor* pac_; 00334 }; 00335 typedef QMap< QString, ArgFactoryEntry > ArgFactory; 00336 bool RegisterType( const QString& typeName, QArgConstructor* qac, PyArgConstructor* pac, bool overwrite ) { 00337 const bool typeExist = argFactory_.contains( typeName ); 00338 if( typeExist && !overwrite ) return false; 00339 argFactory_[ typeName ] = ArgFactoryEntry( typeName, qac, pac ); 00340 return true; 00341 } 00342 Type* ExistingType( const QMetaObject* mo, PyObject* module ) { 00343 for( Types::iterator i = types_.begin(); i != types_.end(); ++i ) { 00344 if( i->metaObject->className() == mo->className() && 00345 i->pyModule == module ) return &( *i ); 00346 } 00347 return 0; 00348 } 00349 typedef QMap< QVariant::Type, QVariantToPyObject* > QVariantToPyObjectMapType; 00350 typedef QMap< QVariant::Type, PyObjectToQVariant* > PyObjectToQVariantMapType; 00351 private: 00352 static PyObject* PyQObjectConnect( PyObject* self, PyObject* args ); 00353 static PyObject* PyQObjectDisconnect( PyObject* self, PyObject* args ); 00354 static PyObject* PyQObjectIsForeignOwned( PyObject* self, PyObject* args ); 00355 static PyObject* PyQObjectIsQObject( PyObject* self, PyObject* args ); 00356 static PyObject* PyQObjectAcquire( PyObject* self, PyObject* args ); 00357 static PyObject* PyQObjectRelease( PyObject* self, PyObject* args ); 00358 static PyObject* PyQObjectPtr( PyObject* self, PyObject* args ); 00359 static PyObject* PyQObjectGetter( PyQObject* qobj, void* closure /*method id*/ ); 00360 static int PyQObjectSetter( PyQObject*, PyObject*, void* closure ); 00361 static PyObject* PyQObjectNew( PyTypeObject* type, PyObject*, PyObject* ); 00362 static PyObject* PyQObjectInvokeMethod( PyQObject* self, PyObject* args ); 00363 static int PyQObjectInit( PyQObject* self, PyObject* args, PyObject* kwds ); 00364 static PyObject* PyQObjectTr( PyObject* self, PyObject* args ); 00365 static void PyQObjectDealloc( PyQObject* self ); 00366 private: 00367 PyTypeObject CreatePyType( const Type& type ); 00368 struct ConnectEntry { 00369 PyQObject* pyqobj; 00370 int methodId; 00371 ConnectEntry() : pyqobj( 0 ), methodId( -1 ) {} 00372 ConnectEntry( PyQObject* p, int m ) : pyqobj( p ), methodId( m ) {} 00373 }; 00374 typedef QList< ConnectEntry > ConnectList; 00375 private: 00378 Types types_; 00379 PyCallbackDispatcher dispatcher_; 00380 ArgFactory argFactory_; 00381 QVariantToPyObjectMapType qvariantToPyObject_; 00382 PyObjectToQVariantMapType pyObjectToQVariant_; 00383 static ConnectList endpoints_; //thread_local if needed 00384 static int getterMethodId_; 00385 static bool signal_; 00386 }; 00387 00388 }