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 PythonQtQObjectWrappedCB(QObject* object);
72 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
73 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, const char **class_name);
74 
75 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
76 
77 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) {
78  (reinterpret_cast<T*>(object))->_wrapper = wrapper;
79 }
80 
82 template<class T1, class T2> int PythonQtUpcastingOffset() {
83  return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100))))
84  - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100))));
85 }
86 
89 
91 template<class T> QObject* PythonQtCreateObject() { return new T(); };
92 
94 
102 class PYTHONQT_EXPORT PythonQt : public QObject {
103 
104  Q_OBJECT
105 
106 public:
107 
109  enum InitFlags {
110  RedirectStdOut = 1,
111  IgnoreSiteModule = 2,
112  ExternalHelp = 4,
113  PythonAlreadyInitialized = 8
114  };
115 
117  enum TypeSlots {
118  Type_Add = 1,
119  Type_Subtract = 1 << 1,
120  Type_Multiply = 1 << 2,
121  Type_Divide = 1 << 3,
122  Type_Mod = 1 << 4,
123  Type_And = 1 << 5,
124  Type_Or = 1 << 6,
125  Type_Xor = 1 << 7,
126  Type_LShift = 1 << 8,
127  Type_RShift = 1 << 9,
128 
129  Type_InplaceAdd = 1 << 10,
130  Type_InplaceSubtract = 1 << 11,
131  Type_InplaceMultiply = 1 << 12,
132  Type_InplaceDivide = 1 << 13,
133  Type_InplaceMod = 1 << 14,
134  Type_InplaceAnd = 1 << 15,
135  Type_InplaceOr = 1 << 16,
136  Type_InplaceXor = 1 << 17,
137  Type_InplaceLShift = 1 << 18,
138  Type_InplaceRShift = 1 << 19,
139 
140  // Not yet needed/nicely mappable/generated...
141  //Type_Positive = 1 << 29,
142  //Type_Negative = 1 << 29,
143  //Type_Abs = 1 << 29,
144  //Type_Hash = 1 << 29,
145 
146  Type_Invert = 1 << 29,
147  Type_RichCompare = 1 << 30,
148  Type_NonZero = 1 << 31,
149 
150  };
151 
154  Enter = 1,
155  Leave = 2
156  };
157 
160  typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName, PyObject* args);
161 
162  //---------------------------------------------------------------------------
164 
165 
169  static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
170 
172  static void cleanup();
173 
175  static PythonQt* self();
176 
178 
180  enum ObjectType {
186  CallOverloads
187  };
188 
189 
190  //---------------------------------------------------------------------------
192 
193 
196  void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0);
197 
200  void setRedirectStdInCallbackEnabled(bool enabled);
201 
203 
204  //---------------------------------------------------------------------------
206 
207 
209  PythonQtObjectPtr getMainModule();
210 
213  PythonQtObjectPtr importModule(const QString& name);
214 
219  PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
220 
225  PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
226 
229  PythonQtObjectPtr createUniqueModule();
230 
232 
233  //---------------------------------------------------------------------------
235 
236 
238  void overwriteSysPath(const QStringList& paths);
239 
241  void addSysPath(const QString& path);
242 
244  void setModuleImportPath(PyObject* module, const QStringList& paths);
245 
247 
248  //---------------------------------------------------------------------------
250 
251 
253  /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
254  you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
255  void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
256 
259 
265  void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
266 
269  void registerQObjectClassNames(const QStringList& names);
270 
275  bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
276 
278  void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
279 
281 
282  //---------------------------------------------------------------------------
284 
285 
287  PythonQtObjectPtr parseFile(const QString& filename);
288 
291  QVariant evalCode(PyObject* object, PyObject* pycode);
292 
294  QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
295 
297  void evalFile(PyObject* object, const QString& filename);
298 
300 
301  //---------------------------------------------------------------------------
303 
304 
306  bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
307 
309  bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
310 
312  bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
313 
315  bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
316 
318 
319  //---------------------------------------------------------------------------
321 
322 
324  void addObject(PyObject* object, const QString& name, QObject* qObject);
325 
327  void addVariable(PyObject* object, const QString& name, const QVariant& v);
328 
330  void removeVariable(PyObject* module, const QString& name);
331 
333  QVariant getVariable(PyObject* object, const QString& name);
334 
336  QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
338  QStringList introspectObject(PyObject* object, ObjectType type);
343  QStringList introspectType(const QString& typeName, ObjectType type);
344 
347  PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
348 
350  QString getReturnTypeOfWrappedMethod(PyObject* module, const QString& objectname);
352  QString getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName);
354 
355  //---------------------------------------------------------------------------
357 
358 
360  QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
361 
363  QVariant call(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
364 
366  PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
367 
369 
370  //---------------------------------------------------------------------------
372 
373 
378 
399  void addInstanceDecorators(QObject* o);
400 
403 
417  void addClassDecorators(QObject* o);
418 
420  void addDecorators(QObject* o);
421 
423  void addWrapperFactory(PythonQtCppWrapperFactory* factory);
424 
426  void addWrapperFactory(PythonQtForeignWrapperFactory* factory);
427 
429  void removeWrapperFactory(PythonQtCppWrapperFactory* factory);
430 
432  void removeWrapperFactory(PythonQtForeignWrapperFactory* factory);
433 
435 
436  //---------------------------------------------------------------------------
438 
439 
449  void setImporter(PythonQtImportFileInterface* importInterface);
450 
457  void installDefaultImporter() { setImporter(NULL); }
458 
460  void setImporterIgnorePaths(const QStringList& paths);
461 
463  const QStringList& getImporterIgnorePaths();
464 
466  static PythonQtImportFileInterface* importInterface();
467 
469 
470  //---------------------------------------------------------------------------
472 
473 
475  static PythonQtPrivate* priv() { return _self->_p; }
476 
479  void clearNotFoundCachedMembers();
480 
483  bool handleError();
484 
486  bool hadError()const;
487 
490  void clearError();
491 
494  void setSystemExitExceptionHandlerEnabled(bool value);
495 
498  bool systemExitExceptionHandlerEnabled() const;
499 
501  void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
503  void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
504 
506  static void qObjectNoLongerWrappedCB(QObject* o);
507 
509  PyObject* helpCalled(PythonQtClassInfo* info);
510 
513  PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
514 
516  void setProfilingCallback(ProfilingCB* cb);
517 
519 
520 Q_SIGNALS:
522  void pythonStdOut(const QString& str);
524  void pythonStdErr(const QString& str);
525 
527  void pythonHelpRequest(const QByteArray& cppClassName);
528 
532  void systemExitExceptionRaised(int exitCode);
533 
534 private:
535  void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
536 
537  QString getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context);
538 
539  PyObject* getObjectByType(const QString& typeName);
540 
542  static void stdOutRedirectCB(const QString& str);
544  static void stdErrRedirectCB(const QString& str);
545 
547  PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
548 
549  PythonQt(int flags, const QByteArray& pythonQtModuleName);
550  ~PythonQt();
551 
552  static PythonQt* _self;
553  static int _uniqueModuleCount;
554 
555  PythonQtPrivate* _p;
556 
557 };
558 
560 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
561 
562  Q_OBJECT
563 
564 public:
565  PythonQtPrivate();
566  ~PythonQtPrivate();
567 
569  StaticDecorator = 1,
570  ConstructorDecorator = 2,
571  DestructorDecorator = 4,
572  InstanceDecorator = 8,
573  AllDecorators = 0xffff
574  };
575 
577  const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
578 
580  bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
581 
583  void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
585  void removeWrapperPointer(void* obj);
586 
588  void shellClassDeleted(void* shellClass);
589 
591  void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj);
592 
594  bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
595 
597  void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
598 
600  PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
601 
603  void removeSignalEmitter(QObject* obj);
604 
606  PyObject* wrapQObject(QObject* obj);
607 
609  PyObject* wrapPtr(void* ptr, const QByteArray& name);
610 
612  static PyObject* wrapMemoryAsBuffer(const void* data, Py_ssize_t size);
613 
615  static PyObject* wrapMemoryAsBuffer(void* data, Py_ssize_t size);
616 
618  /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
619  you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
620  void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
621 
624 
630  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);
631 
634  void registerQObjectClassNames(const QStringList& names);
635 
637  void addDecorators(QObject* o, int decoTypes);
638 
640  PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module, const QByteArray& pythonClassName);
641 
643  static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
644 
646  static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
647 
649  PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
650 
652  PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
653 
655  PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
656 
658  PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
659 
661  PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
662 
664  static PyObject* dummyTuple();
665 
667  void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
668 
670  PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
671 
673  PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
674 
676  QString getSignature(PyObject* object);
677 
679  bool isMethodDescriptor(PyObject* object) const;
680 
681 private:
683  void setupSharedLibrarySuffixes();
684 
686  void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
687 
689  PyObject* packageByName(const char* name);
690 
692  PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
693 
695  QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
696 
698  QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
699 
701  QHash<QByteArray, bool> _knownQObjectClassNames;
702 
704  QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
705 
707  PythonQtObjectPtr _pythonQtModule;
708 
710  QByteArray _pythonQtModuleName;
711 
713  PythonQtImportFileInterface* _importInterface;
714 
716  PythonQtQFileImporter* _defaultImporter;
717 
718  PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
719  PythonQtQObjectWrappedCB* _wrappedCB;
720 
721  QStringList _importIgnorePaths;
722  QStringList _sharedLibrarySuffixes;
723 
725  QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
726 
727  QList<PythonQtForeignWrapperFactory*> _foreignWrapperFactories;
728 
729  QHash<QByteArray, PyObject*> _packages;
730 
731  PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
732 
733  PythonQt::ProfilingCB* _profilingCB;
734 
735  int _initFlags;
736  int _PythonQtObjectPtr_metaId;
737 
738  bool _hadError;
739  bool _systemExitExceptionHandlerEnabled;
740 
741  friend class PythonQt;
742 };
743 
744 #endif