From 2184742f9ca8d11fe1b54e4a3336046c6b3814ff 2011-11-14 13:28:00 From: florianlink Date: 2011-11-14 13:28:00 Subject: [PATCH] added initial version of foreign wrappers, needs testing git-svn-id: svn://svn.code.sf.net/p/pythonqt/code/trunk@206 ea8d5007-eb21-0410-b261-ccb3ea6e24a9 --- diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index cafd340..117c492 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -391,6 +391,15 @@ PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name) return (PyObject*)wrap; } + // not a known QObject, try to wrap via foreign wrapper factories + PyObject* foreignWrapper = NULL; + for (int i=0; i<_foreignWrapperFactories.size(); i++) { + foreignWrapper = _foreignWrapperFactories.at(i)->wrap(name, ptr); + if (foreignWrapper) { + return foreignWrapper; + } + } + // not a known QObject, so try our wrapper factory: QObject* wrapper = NULL; for (int i=0; i<_cppWrapperFactories.size(); i++) { @@ -415,8 +424,6 @@ PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name) info->setMetaObject(wrapper->metaObject()); } - // TODO XXX: delegate wrapping via CB here (pass name and ptr) - wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr); // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1()); } else { @@ -965,6 +972,11 @@ void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory) _p->_cppWrapperFactories.append(factory); } +void PythonQt::addWrapperFactory( PythonQtForeignWrapperFactory* factory ) +{ + _p->_foreignWrapperFactories.append(factory); +} + //--------------------------------------------------------------------------------------------------- PythonQtPrivate::PythonQtPrivate() { @@ -1316,3 +1328,15 @@ PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* p } return result; } + +void* PythonQtPrivate::unwrapForeignWrapper( const QByteArray& classname, PyObject* obj ) +{ + void* foreignObject = NULL; + for (int i=0; i<_foreignWrapperFactories.size(); i++) { + foreignObject = _foreignWrapperFactories.at(i)->unwrap(classname, obj); + if (foreignObject) { + return foreignObject; + } + } + return NULL; +} \ No newline at end of file diff --git a/src/PythonQt.h b/src/PythonQt.h index a015d8e..35d780d 100644 --- a/src/PythonQt.h +++ b/src/PythonQt.h @@ -64,6 +64,7 @@ class PythonQtMethodInfo; class PythonQtSignalReceiver; class PythonQtImportFileInterface; class PythonQtCppWrapperFactory; +class PythonQtForeignWrapperFactory; class PythonQtQFileImporter; typedef void PythonQtQObjectWrappedCB(QObject* object); @@ -409,6 +410,9 @@ public: //! add the given factory to PythonQt (ownership stays with caller) void addWrapperFactory(PythonQtCppWrapperFactory* factory); + //! add the given factory to PythonQt (ownership stays with caller) + void addWrapperFactory(PythonQtForeignWrapperFactory* factory); + //@} //--------------------------------------------------------------------------- @@ -538,6 +542,9 @@ public: //! remove the wrapper ptr again void removeWrapperPointer(void* obj); + //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories + void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj); + //! add parent class relation bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset); @@ -660,6 +667,8 @@ private: //! the cpp object wrapper factories QList _cppWrapperFactories; + QList _foreignWrapperFactories; + QHash _packages; PythonQtClassInfo* _currentClassInfoForClassWrapperCreation; diff --git a/src/PythonQtConversion.cpp b/src/PythonQtConversion.cpp index 1d69f36..c46e6cd 100644 --- a/src/PythonQtConversion.cpp +++ b/src/PythonQtConversion.cpp @@ -386,19 +386,22 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i } else if (info.name == "PyObject") { // handle low level PyObject directly PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr); - } - // TODO XXX: pass obj and name and add when it returns a pointer - else if (obj == Py_None) { + } else if (obj == Py_None) { // None is treated as a NULL ptr PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr); } else { - // if we are not strict, we try if we are passed a 0 integer - if (!strict) { - bool ok; - int value = PyObjGetInt(obj, true, ok); - if (ok && value==0) { - // TODOXXX is this wise? or should it be expected from the programmer to use None? - PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr); + void* foreignWrapper = PythonQt::priv()->unwrapForeignWrapper(info.name, obj); + if (foreignWrapper) { + PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, foreignWrapper, ptr); + } else { + // if we are not strict, we try if we are passed a 0 integer + if (!strict) { + bool ok; + int value = PyObjGetInt(obj, true, ok); + if (ok && value==0) { + // TODOXXX is this wise? or should it be expected from the programmer to use None? + PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr); + } } } } diff --git a/src/PythonQtCppWrapperFactory.h b/src/PythonQtCppWrapperFactory.h index ff9cdbd..c83b227 100644 --- a/src/PythonQtCppWrapperFactory.h +++ b/src/PythonQtCppWrapperFactory.h @@ -54,7 +54,25 @@ public: virtual ~PythonQtCppWrapperFactory() {}; //! create a wrapper for the given object - virtual QObject* create(const QByteArray& name, void *ptr) = 0; + virtual QObject* create(const QByteArray& classname, void *ptr) = 0; + +}; + +//! Factory interface for C++ classes that can be mapped directly from/to +//! Python with other means than PythonQt/QObjects. +class PYTHONQT_EXPORT PythonQtForeignWrapperFactory +{ +public: + PythonQtForeignWrapperFactory() {}; + virtual ~PythonQtForeignWrapperFactory() {}; + + //! create a Python object (with new reference count), wrapping the given \p ptr as class of type \p classname + //! Return NULL (and not Py_None) if the object could not be wrapped. + virtual PyObject* wrap(const QByteArray& classname, void *ptr) = 0; + + //! unwrap the given object to a C++ object of type \p classname if possible + //! Return NULL otherwise. + virtual void* unwrap(const QByteArray& classname, PyObject* object) = 0; };