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 
370  //---------------------------------------------------------------------------
372 
373 
375  void addObject(PyObject* object, const QString& name, QObject* qObject);
376 
378  void addVariable(PyObject* object, const QString& name, const QVariant& v);
379 
381  void removeVariable(PyObject* module, const QString& name);
382 
384  QVariant getVariable(PyObject* object, const QString& name);
385 
387  QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
389  QStringList introspectObject(PyObject* object, ObjectType type);
394  QStringList introspectType(const QString& typeName, ObjectType type);
395 
398  PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
399 
401  QString getReturnTypeOfWrappedMethod(PyObject* module, const QString& objectname);
403  QString getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName);
405 
406  //---------------------------------------------------------------------------
408 
409 
411  QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
412 
414  QVariant call(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
415 
417  PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
418 
420 
421  //---------------------------------------------------------------------------
423 
424 
429 
450  void addInstanceDecorators(QObject* o);
451 
454 
468  void addClassDecorators(QObject* o);
469 
471  void addDecorators(QObject* o);
472 
474  void addWrapperFactory(PythonQtCppWrapperFactory* factory);
475 
477  void addWrapperFactory(PythonQtForeignWrapperFactory* factory);
478 
480  void removeWrapperFactory(PythonQtCppWrapperFactory* factory);
481 
483  void removeWrapperFactory(PythonQtForeignWrapperFactory* factory);
484 
486 
487  //---------------------------------------------------------------------------
489 
490 
500  void setImporter(PythonQtImportFileInterface* importInterface);
501 
508  void installDefaultImporter() { setImporter(NULL); }
509 
511  void setImporterIgnorePaths(const QStringList& paths);
512 
514  const QStringList& getImporterIgnorePaths();
515 
517  static PythonQtImportFileInterface* importInterface();
518 
520 
521  //---------------------------------------------------------------------------
523 
524 
526  static PythonQtPrivate* priv() { return _self->_p; }
527 
530  void clearNotFoundCachedMembers();
531 
534  bool handleError();
535 
537  bool hadError()const;
538 
541  void clearError();
542 
545  void setSystemExitExceptionHandlerEnabled(bool value);
546 
549  bool systemExitExceptionHandlerEnabled() const;
550 
552  void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
554  void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
555 
557  static void qObjectNoLongerWrappedCB(QObject* o);
558 
560  PyObject* helpCalled(PythonQtClassInfo* info);
561 
564  PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
565 
567  void setProfilingCallback(ProfilingCB* cb);
568 
570 
571 Q_SIGNALS:
573  void pythonStdOut(const QString& str);
575  void pythonStdErr(const QString& str);
576 
578  void pythonHelpRequest(const QByteArray& cppClassName);
579 
583  void systemExitExceptionRaised(int exitCode);
584 
585 private:
586  void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
587 
588  QString getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context);
589 
590  PyObject* getObjectByType(const QString& typeName);
591 
593  static void stdOutRedirectCB(const QString& str);
595  static void stdErrRedirectCB(const QString& str);
596 
598  PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
599 
600  PythonQt(int flags, const QByteArray& pythonQtModuleName);
601  ~PythonQt();
602  static PythonQt* _self;
603  static int _uniqueModuleCount;
604 
605  PythonQtPrivate* _p;
606 
607 };
608 
609 class PythonQtDebugAPI;
610 
612 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
613 
614  Q_OBJECT
615 
616 public:
617  PythonQtPrivate();
618  ~PythonQtPrivate();
619 
621  StaticDecorator = 1,
622  ConstructorDecorator = 2,
623  DestructorDecorator = 4,
624  InstanceDecorator = 8,
625  AllDecorators = 0xffff
626  };
627 
629  const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
630 
632  bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
633 
635  void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
637  void removeWrapperPointer(void* obj);
638 
640  void shellClassDeleted(void* shellClass);
641 
643  void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj);
644 
646  bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
647 
649  void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
650 
652  PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
653 
655  void removeSignalEmitter(QObject* obj);
656 
658  PyObject* wrapQObject(QObject* obj);
659 
663  PyObject* wrapPtr(void* ptr, const QByteArray& name, bool passOwnership = false);
664 
666  static PyObject* wrapMemoryAsBuffer(const void* data, Py_ssize_t size);
667 
669  static PyObject* wrapMemoryAsBuffer(void* data, Py_ssize_t size);
670 
672  /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
673  you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
674  void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
675 
678 
684  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);
685 
688  void registerQObjectClassNames(const QStringList& names);
689 
691  void addDecorators(QObject* o, int decoTypes);
692 
694  PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module, const QByteArray& pythonClassName);
695 
697  static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
698 
700  static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
701 
703  PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
704 
706  PythonQtClassInfo* getClassInfo(const QMetaObject* meta);
707 
709  PythonQtClassInfo* getClassInfo(const QByteArray& className);
710 
713  void registerLazyClass(const QByteArray& name, const QByteArray& moduleToImport);
714 
716  PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
717 
719  PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
720 
722  static PyObject* dummyTuple();
723 
725  void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
726 
728  PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
729 
731  PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
732 
734  QString getSignature(PyObject* object);
735 
737  bool isMethodDescriptor(PyObject* object) const;
738 
739 private:
741  void setupSharedLibrarySuffixes();
742 
744  void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
745 
747  PyObject* packageByName(const char* name);
748 
750  PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
751 
753  QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
754 
756  QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
757 
759  QHash<QByteArray, bool> _knownQObjectClassNames;
760 
762  QHash<QByteArray, QByteArray> _knownLazyClasses;
763 
765  QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
766 
768  PythonQtObjectPtr _pythonQtModule;
769 
771  QByteArray _pythonQtModuleName;
772 
774  PythonQtImportFileInterface* _importInterface;
775 
777  PythonQtQFileImporter* _defaultImporter;
778 
779  PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
780  PythonQtQObjectWrappedCB* _wrappedCB;
781 
782  QStringList _importIgnorePaths;
783  QStringList _sharedLibrarySuffixes;
784 
786  QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
787 
788  QList<PythonQtForeignWrapperFactory*> _foreignWrapperFactories;
789 
790  QHash<QByteArray, PyObject*> _packages;
791 
792  PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
793 
794  PythonQt::ProfilingCB* _profilingCB;
795 
796  PythonQtDebugAPI* _debugAPI;
797 
798  int _initFlags;
799  int _PythonQtObjectPtr_metaId;
800 
801  bool _hadError;
802  bool _systemExitExceptionHandlerEnabled;
803 
804  friend class PythonQt;
805 };
806 
807 #endif