SourceForge.net Logo
PythonQt
PythonQt.h
Go to the documentation of this file.
1 #ifndef _PYTHONQT_H
2 #define _PYTHONQT_H
3 
4 /*
5  *
6  * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * Further, this software is distributed without any warranty that it is
19  * free of the rightful claim of any third person regarding infringement
20  * or the like. Any license provided herein, whether implied or
21  * otherwise, applies only to this software file. Patent licenses, if
22  * any, provided herein do not apply to combinations of this program with
23  * other software, or any other product whatsoever.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28  *
29  * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30  * 28359 Bremen, Germany or:
31  *
32  * http://www.mevis.de
33  *
34  */
35 
36 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44 
45 #include "PythonQtUtils.h"
46 #include "PythonQtSystem.h"
48 #include "PythonQtClassWrapper.h"
49 #include "PythonQtSlot.h"
50 #include "PythonQtObjectPtr.h"
51 #include "PythonQtStdIn.h"
52 #include <QObject>
53 #include <QVariant>
54 #include <QList>
55 #include <QHash>
56 #include <QByteArray>
57 #include <QStringList>
58 #include <QtDebug>
59 #include <iostream>
60 
61 
62 class PythonQtClassInfo;
63 class PythonQtPrivate;
64 class PythonQtMethodInfo;
70 
71 typedef void PythonQtVoidPtrCB(void* object);
72 typedef void PythonQtQObjectWrappedCB(QObject* object);
73 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
74 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, const char **class_name);
75 
76 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
77 
78 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) {
79  (reinterpret_cast<T*>(object))->_wrapper = wrapper;
80 }
81 
85 template<class T>
87 {
88  public:
90  PythonQtPassOwnershipToCPP(const T& t):_t(t) {}
92  operator T() const { return _t; }
93 
96  T _t;
97 };
98 
102 template<class T>
104 {
105 public:
109  operator T() const { return _t; }
110 
113  T _t;
114 };
115 
119 template<class T>
121 {
122 public:
124  PythonQtNewOwnerOfThis(const T& t):_t(t) {}
126  operator T() const { return _t; }
127 
130  T _t;
131 };
132 
133 
135 template<class T1, class T2> int PythonQtUpcastingOffset() {
136  return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100))))
137  - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100))));
138 }
139 
142 
144 template<class T> QObject* PythonQtCreateObject() { return new T(); };
145 
147 
155 class PYTHONQT_EXPORT PythonQt : public QObject {
156 
157  Q_OBJECT
158 
159 public:
160 
162  enum InitFlags {
163  RedirectStdOut = 1,
164  IgnoreSiteModule = 2,
165  ExternalHelp = 4,
166  PythonAlreadyInitialized = 8
167  };
168 
170  enum TypeSlots {
171  Type_Add = 1,
172  Type_Subtract = 1 << 1,
173  Type_Multiply = 1 << 2,
174  Type_Divide = 1 << 3,
175  Type_Mod = 1 << 4,
176  Type_And = 1 << 5,
177  Type_Or = 1 << 6,
178  Type_Xor = 1 << 7,
179  Type_LShift = 1 << 8,
180  Type_RShift = 1 << 9,
181 
182  Type_InplaceAdd = 1 << 10,
183  Type_InplaceSubtract = 1 << 11,
184  Type_InplaceMultiply = 1 << 12,
185  Type_InplaceDivide = 1 << 13,
186  Type_InplaceMod = 1 << 14,
187  Type_InplaceAnd = 1 << 15,
188  Type_InplaceOr = 1 << 16,
189  Type_InplaceXor = 1 << 17,
190  Type_InplaceLShift = 1 << 18,
191  Type_InplaceRShift = 1 << 19,
192 
193  Type_Length = 1 << 20,
194  Type_MappingSetItem = 1 << 21,
195  Type_MappingGetItem = 1 << 22,
196 
197  Type_Invert = 1 << 29,
198  Type_RichCompare = 1 << 30,
199  Type_NonZero = 1 << 31,
200 
201  };
202 
205  Enter = 1,
206  Leave = 2
207  };
208 
211  typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName, PyObject* args);
212 
213  //---------------------------------------------------------------------------
215 
216 
220  static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
221 
223  static void cleanup();
224 
226  static PythonQt* self();
227 
229 
231  enum ObjectType {
237  CallOverloads
238  };
239 
240 
241  //---------------------------------------------------------------------------
243 
244 
247  void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0);
248 
251  void setRedirectStdInCallbackEnabled(bool enabled);
252 
254 
255  //---------------------------------------------------------------------------
257 
258 
260  PythonQtObjectPtr getMainModule();
261 
264  PythonQtObjectPtr importModule(const QString& name);
265 
270  PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
271 
276  PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
277 
280  PythonQtObjectPtr createUniqueModule();
281 
283 
284  //---------------------------------------------------------------------------
286 
287 
289  void overwriteSysPath(const QStringList& paths);
290 
292  void addSysPath(const QString& path);
293 
295  void setModuleImportPath(PyObject* module, const QStringList& paths);
296 
298 
299  //---------------------------------------------------------------------------
301 
302 
304  /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
305  you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
306  void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
307 
310 
316  void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
317 
320  void registerQObjectClassNames(const QStringList& names);
321 
326  bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
327 
329  void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
330 
332 
333  //---------------------------------------------------------------------------
335 
336 
338  PythonQtObjectPtr parseFile(const QString& filename);
339 
342  QVariant evalCode(PyObject* object, PyObject* pycode);
343 
345  QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
346 
348  void evalFile(PyObject* object, const QString& filename);
349 
351 
352  //---------------------------------------------------------------------------
354 
355 
357  bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
358 
360  bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
361 
363  bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
364 
366  bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
367 
369  void removeSignalHandlers();
370 
372 
373  //---------------------------------------------------------------------------
375 
376 
378  void addObject(PyObject* object, const QString& name, QObject* qObject);
379 
381  void addVariable(PyObject* object, const QString& name, const QVariant& v);
382 
384  void removeVariable(PyObject* module, const QString& name);
385 
387  QVariant getVariable(PyObject* object, const QString& name);
388 
390  QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
392  QStringList introspectObject(PyObject* object, ObjectType type);
397  QStringList introspectType(const QString& typeName, ObjectType type);
398 
401  PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
402 
404  QString getReturnTypeOfWrappedMethod(PyObject* module, const QString& objectname);
406  QString getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName);
408 
409  //---------------------------------------------------------------------------
411 
412 
414  QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
415 
417  QVariant call(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
418 
420  PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
421 
423 
424  //---------------------------------------------------------------------------
426 
427 
432 
453  void addInstanceDecorators(QObject* o);
454 
457 
471  void addClassDecorators(QObject* o);
472 
474  void addDecorators(QObject* o);
475 
477  void addWrapperFactory(PythonQtCppWrapperFactory* factory);
478 
480  void addWrapperFactory(PythonQtForeignWrapperFactory* factory);
481 
483  void removeWrapperFactory(PythonQtCppWrapperFactory* factory);
484 
486  void removeWrapperFactory(PythonQtForeignWrapperFactory* factory);
487 
489 
490  //---------------------------------------------------------------------------
492 
493 
503  void setImporter(PythonQtImportFileInterface* importInterface);
504 
511  void installDefaultImporter() { setImporter(NULL); }
512 
514  void setImporterIgnorePaths(const QStringList& paths);
515 
517  const QStringList& getImporterIgnorePaths();
518 
520  static PythonQtImportFileInterface* importInterface();
521 
523 
524  //---------------------------------------------------------------------------
526 
527 
529  static PythonQtPrivate* priv() { return _self->_p; }
530 
533  void clearNotFoundCachedMembers();
534 
537  bool handleError();
538 
540  bool hadError()const;
541 
544  void clearError();
545 
548  void setSystemExitExceptionHandlerEnabled(bool value);
549 
552  bool systemExitExceptionHandlerEnabled() const;
553 
555  void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
557  void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
558 
560  static void qObjectNoLongerWrappedCB(QObject* o);
561 
563  PyObject* helpCalled(PythonQtClassInfo* info);
564 
567  PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
568 
570  void setProfilingCallback(ProfilingCB* cb);
571 
573 
574 Q_SIGNALS:
576  void pythonStdOut(const QString& str);
578  void pythonStdErr(const QString& str);
579 
581  void pythonHelpRequest(const QByteArray& cppClassName);
582 
586  void systemExitExceptionRaised(int exitCode);
587 
588 private:
589  void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
590 
591  QString getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context);
592 
593  PyObject* getObjectByType(const QString& typeName);
594 
596  static void stdOutRedirectCB(const QString& str);
598  static void stdErrRedirectCB(const QString& str);
599 
601  PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
602 
603  PythonQt(int flags, const QByteArray& pythonQtModuleName);
604  ~PythonQt();
605  static PythonQt* _self;
606  static int _uniqueModuleCount;
607 
608  PythonQtPrivate* _p;
609 
610 };
611 
612 class PythonQtDebugAPI;
613 
615 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
616 
617  Q_OBJECT
618 
619 public:
620  PythonQtPrivate();
621  ~PythonQtPrivate();
622 
624  StaticDecorator = 1,
625  ConstructorDecorator = 2,
626  DestructorDecorator = 4,
627  InstanceDecorator = 8,
628  AllDecorators = 0xffff
629  };
630 
632  const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
633 
635  bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
636 
638  void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
640  void removeWrapperPointer(void* obj);
641 
643  void shellClassDeleted(void* shellClass);
644 
646  void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj);
647 
649  bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
650 
652  void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
653 
655  PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
656 
658  void removeSignalEmitter(QObject* obj);
659 
661  PyObject* wrapQObject(QObject* obj);
662 
666  PyObject* wrapPtr(void* ptr, const QByteArray& name, bool passOwnership = false);
667 
669  static PyObject* wrapMemoryAsBuffer(const void* data, Py_ssize_t size);
670 
672  static PyObject* wrapMemoryAsBuffer(void* data, Py_ssize_t size);
673 
675  /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
676  you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
677  void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
678 
681 
687  void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
688 
691  void registerQObjectClassNames(const QStringList& names);
692 
694  void addDecorators(QObject* o, int decoTypes);
695 
697  PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module, const QByteArray& pythonClassName);
698 
700  static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
701 
703  static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
704 
706  PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
707 
709  PythonQtClassInfo* getClassInfo(const QMetaObject* meta);
710 
712  PythonQtClassInfo* getClassInfo(const QByteArray& className);
713 
716  void registerLazyClass(const QByteArray& name, const QByteArray& moduleToImport);
717 
719  PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
720 
722  PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
723 
725  static PyObject* dummyTuple();
726 
728  void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
729 
731  PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
732 
734  PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
735 
737  QString getSignature(PyObject* object);
738 
740  bool isMethodDescriptor(PyObject* object) const;
741 
743  const QMetaObject* getDynamicMetaObject(PythonQtInstanceWrapper* wrapper, const QMetaObject* prototypeMetaObject);
744 
745  void buildDynamicMetaObject(PythonQtClassWrapper* type, const QMetaObject* prototypeMetaObject);
746 
748  int handleMetaCall(QObject* object, PythonQtInstanceWrapper* wrapper, QMetaObject::Call call, int id, void** args);
749 
751  void callMethodInPython(QMetaMethod &method, PythonQtInstanceWrapper* wrapper, void** args);
752 
753 private:
755  void setupSharedLibrarySuffixes();
756 
758  void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
759 
761  PyObject* packageByName(const char* name);
762 
764  PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
765 
767  QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
768 
770  QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
771 
773  QHash<QByteArray, bool> _knownQObjectClassNames;
774 
776  QHash<QByteArray, QByteArray> _knownLazyClasses;
777 
779  QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
780 
782  PythonQtObjectPtr _pythonQtModule;
783 
785  QByteArray _pythonQtModuleName;
786 
788  PythonQtImportFileInterface* _importInterface;
789 
791  PythonQtQFileImporter* _defaultImporter;
792 
793  PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
794  PythonQtQObjectWrappedCB* _wrappedCB;
795 
796  QStringList _importIgnorePaths;
797  QStringList _sharedLibrarySuffixes;
798 
800  QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
801 
802  QList<PythonQtForeignWrapperFactory*> _foreignWrapperFactories;
803 
804  QHash<QByteArray, PyObject*> _packages;
805 
806  PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
807 
808  PythonQt::ProfilingCB* _profilingCB;
809 
810  PythonQtDebugAPI* _debugAPI;
811 
812  int _initFlags;
813  int _PythonQtObjectPtr_metaId;
814 
815  bool _hadError;
816  bool _systemExitExceptionHandlerEnabled;
817 
818  friend class PythonQt;
819 };
820 
821 #endif
void installDefaultImporter()
Definition: PythonQt.h:511
Factory interface for C++ classes that can be wrapped by QObject objects.
InitFlags
flags that can be passed to PythonQt::init()
Definition: PythonQt.h:162
void ProfilingCB(ProfilingCallbackState state, const char *className, const char *methodName, PyObject *args)
Definition: PythonQt.h:211
void * PythonQtPolymorphicHandlerCB(const void *ptr, const char **class_name)
Definition: PythonQt.h:74
a Python wrapper object for Qt objects and C++ objects (that are themselves wrapped by wrapper QObjec...
a class that stores all required information about a Qt object (and an optional associated C++ class ...
ObjectType
defines the object types for introspection
Definition: PythonQt.h:231
QByteArray typeName(const QMetaMethod &method)
Definition: PythonQtUtils.h:72
QString PythonQtInputChangedCB(void *callData)
declares the callback that is called from the write() function
Definition: PythonQtStdIn.h:54
void PythonQtQObjectWrappedCB(QObject *object)
Definition: PythonQt.h:72
Some helper methods that allow testing of the ownership.
static PythonQtPrivate * priv()
get access to internal data (should not be used on the public API, but is used by some C functions) ...
Definition: PythonQt.h:529
void PythonQtVoidPtrCB(void *object)
Definition: PythonQt.h:71
internal PythonQt details
Definition: PythonQt.h:615
void PythonQtQObjectNoLongerWrappedCB(QObject *object)
Definition: PythonQt.h:73
PythonQt::ProfilingCB * profilingCB() const
returns the profiling callback, which may be NULL
Definition: PythonQt.h:734
PythonQtNewOwnerOfThis(const T &t)
Allow conversion from T to PythonQtNewOwnerOfThis
Definition: PythonQt.h:124
QByteArray methodName(const QMetaMethod &method)
Definition: PythonQtUtils.h:61
receives all signals for one QObject
PythonQtPassOwnershipToPython(const T &t)
Allow conversion from T to PythonQtPassOwnershipToPython
Definition: PythonQt.h:107
bool isPythonQtObjectPtrMetaId(int id)
returns if the id is the id for PythonQtObjectPtr
Definition: PythonQt.h:635
#define PYTHONQT_EXPORT
PythonQtPassOwnershipToCPP(const T &t)
Allow conversion from T to PythonQtPassOwnershipToCPP
Definition: PythonQt.h:90
struct _object PyObject
ProfilingCallbackState
enum for profiling callback
Definition: PythonQt.h:204
int PythonQtUpcastingOffset()
returns the offset that needs to be added to upcast an object of type T1 to T2
Definition: PythonQt.h:135
QByteArray signature(const QMetaMethod &method)
Definition: PythonQtUtils.h:53
PythonQtObjectPtr pythonQtModule() const
get access to the PythonQt module
Definition: PythonQt.h:731
a smart pointer that stores a PyObject pointer and that handles reference counting automatically ...
void PythonQtShellSetInstanceWrapperCB(void *object, PythonQtInstanceWrapper *wrapper)
Definition: PythonQt.h:76
void PythonQtSetInstanceWrapperOnShell(void *object, PythonQtInstanceWrapper *wrapper)
Definition: PythonQt.h:78
const QStringList & sharedLibrarySuffixes()
get the suffixes that are used for shared libraries
Definition: PythonQt.h:632
stores information about a specific signal/slot/method
QObject * PythonQtQObjectCreatorFunctionCB()
callback to create a QObject lazily
Definition: PythonQt.h:141
default importer implementation using QFile to load python code
TypeSlots
flags that tell PythonQt which operators to expect on the registered type
Definition: PythonQt.h:170
The main interface to the Python Qt binding, realized as a singleton.
Definition: PythonQt.h:155
QObject * PythonQtCreateObject()
helper template to create a derived QObject class
Definition: PythonQt.h:144