From 87322f2ddb4465facc292ad29850fa68f377bd7f 2011-11-14 10:05:40 From: florianlink Date: 2011-11-14 10:05:40 Subject: [PATCH] merged contributions from https://github.com/commontk/PythonQt/compare/svn-mirror...patched manually reworked the contributions, VTK wrapping needs new callback git-svn-id: svn://svn.code.sf.net/p/pythonqt/code/trunk@200 ea8d5007-eb21-0410-b261-ccb3ea6e24a9 --- diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index 2011de1..cafd340 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -45,6 +45,7 @@ #include "PythonQtMethodInfo.h" #include "PythonQtSignalReceiver.h" #include "PythonQtConversion.h" +#include "PythonQtStdIn.h" #include "PythonQtStdOut.h" #include "PythonQtCppWrapperFactory.h" #include "PythonQtVariants.h" @@ -142,6 +143,8 @@ void PythonQt::cleanup() } } +PythonQt* PythonQt::self() { return _self; } + PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName) { _p = new PythonQtPrivate; @@ -150,7 +153,7 @@ PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName) _p->_PythonQtObjectPtr_metaId = qRegisterMetaType("PythonQtObjectPtr"); if ((flags & PythonAlreadyInitialized) == 0) { - Py_SetProgramName("PythonQt"); + Py_SetProgramName(const_cast("PythonQt")); if (flags & IgnoreSiteModule) { // this prevents the automatic importing of Python site files Py_NoSiteFlag = 1; @@ -185,6 +188,12 @@ PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName) } Py_INCREF(&PythonQtStdOutRedirectType); + // add our own python object types for redirection of stdin + if (PyType_Ready(&PythonQtStdInRedirectType) < 0) { + std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl; + } + Py_INCREF(&PythonQtStdInRedirectType); + initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName); _p->setupSharedLibrarySuffixes(); @@ -213,6 +222,46 @@ PythonQtPrivate::~PythonQtPrivate() { PythonQtMethodInfo::cleanupCachedMethodInfos(); } +void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData) +{ + if (!callback) + { + std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl; + return; + } + + PythonQtObjectPtr sys; + PythonQtObjectPtr in; + sys.setNewRef(PyImport_ImportModule("sys")); + + // Backup original 'sys.stdin' if not yet done + PyRun_SimpleString("if not hasattr(sys, 'pythonqt_original_stdin'):" + "sys.pythonqt_original_stdin = sys.stdin"); + + in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL); + ((PythonQtStdInRedirect*)in.object())->_cb = callback; + ((PythonQtStdInRedirect*)in.object())->_callData = callbackData; + // replace the built in file objects with our own objects + PyModule_AddObject(sys, "stdin", in); + + // Backup custom 'stdin' into 'pythonqt_stdin' + PyRun_SimpleString("sys.pythonqt_stdin = sys.stdin"); +} + +void PythonQt::setRedirectStdInCallbackEnabled(bool enabled) +{ + if (enabled) + { + PyRun_SimpleString("if hasattr(sys, 'pythonqt_stdin'):" + "sys.stdin = sys.pythonqt_stdin"); + } + else + { + PyRun_SimpleString("if hasattr(sys,'pythonqt_original_stdin'):" + "sys.stdin = sys.pythonqt_original_stdin"); + } +} + PythonQtImportFileInterface* PythonQt::importInterface() { return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter; @@ -365,6 +414,9 @@ PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name) // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again! 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 { @@ -1065,11 +1117,19 @@ void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths) void PythonQt::stdOutRedirectCB(const QString& str) { + if (!PythonQt::self()) { + std::cout << str.toLatin1().data() << std::endl; + return; + } emit PythonQt::self()->pythonStdOut(str); } void PythonQt::stdErrRedirectCB(const QString& str) { + if (!PythonQt::self()) { + std::cerr << str.toLatin1().data() << std::endl; + return; + } emit PythonQt::self()->pythonStdErr(str); } diff --git a/src/PythonQt.h b/src/PythonQt.h index a4d53bb..9944ae5 100644 --- a/src/PythonQt.h +++ b/src/PythonQt.h @@ -47,6 +47,7 @@ #include "PythonQtClassWrapper.h" #include "PythonQtSlot.h" #include "PythonQtObjectPtr.h" +#include "PythonQtStdIn.h" #include #include #include @@ -71,11 +72,14 @@ typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name); typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper); -template void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; }; +template void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { + (reinterpret_cast(object))->_wrapper = wrapper; +} //! returns the offset that needs to be added to upcast an object of type T1 to T2 template int PythonQtUpcastingOffset() { - return (((char*)(static_cast(reinterpret_cast(0x100)))) - ((char*)reinterpret_cast(0x100))); + return ((reinterpret_cast(static_cast(reinterpret_cast(0x100)))) + - (reinterpret_cast(reinterpret_cast(0x100)))); } //! callback to create a QObject lazily @@ -166,7 +170,7 @@ public: static void cleanup(); //! get the singleton instance - static PythonQt* self() { return _self; } + static PythonQt* self(); //@} @@ -180,6 +184,21 @@ public: CallOverloads }; + + //--------------------------------------------------------------------------- + //! \name Standard input handling + //@{ + + //! Overwrite default handling of stdin using a custom callback. It internally backup + //! the original 'sys.stdin' into 'sys.pythonqt_original_stdin' + void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0); + + //! Enable or disable stdin custom callback. It resets 'sys.stdin' using either 'sys.pythonqt_stdin' + //! or 'sys.pythonqt_original_stdin' + void setRedirectStdInCallbackEnabled(bool enabled); + + //@} + //--------------------------------------------------------------------------- //! \name Modules //@{ diff --git a/src/PythonQtClassWrapper.h b/src/PythonQtClassWrapper.h index db5f96f..5b7b300 100644 --- a/src/PythonQtClassWrapper.h +++ b/src/PythonQtClassWrapper.h @@ -42,7 +42,7 @@ */ //---------------------------------------------------------------------------------- -#include +#include "PythonQtPythonInclude.h" #include "PythonQtSystem.h" diff --git a/src/PythonQtConversion.cpp b/src/PythonQtConversion.cpp index 64f7bcb..1d69f36 100644 --- a/src/PythonQtConversion.cpp +++ b/src/PythonQtConversion.cpp @@ -386,7 +386,9 @@ 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); - } else if (obj == Py_None) { + } + // TODO XXX: pass obj and name and add when it returns a pointer + else if (obj == Py_None) { // None is treated as a NULL ptr PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr); } else { @@ -673,15 +675,11 @@ QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) { if (val->ob_type == &PyString_Type) { r = QString(PyString_AS_STRING(val)); } else if (PyUnicode_Check(val)) { -#ifdef WIN32 - r = QString::fromUtf16(PyUnicode_AS_UNICODE(val)); -#else PyObject *ptmp = PyUnicode_AsUTF8String(val); if(ptmp) { r = QString::fromUtf8(PyString_AS_STRING(ptmp)); Py_DECREF(ptmp); } -#endif } else if (!strict) { // EXTRA: could also use _Unicode, but why should we? PyObject* str = PyObject_Str(val); @@ -1038,12 +1036,7 @@ PyObject* PythonQtConv::QStringToPyObject(const QString& str) if (str.isNull()) { return PyString_FromString(""); } else { -#ifdef WIN32 - // return PyString_FromString(str.toLatin1().data()); - return PyUnicode_FromUnicode(str.utf16(), str.length()); -#else return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL); -#endif } } diff --git a/src/PythonQtImporter.cpp b/src/PythonQtImporter.cpp index 4a6434b..f9e06a5 100644 --- a/src/PythonQtImporter.cpp +++ b/src/PythonQtImporter.cpp @@ -791,7 +791,7 @@ void PythonQtImport::init() mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc, NULL, PYTHON_API_VERSION); - PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError", + PythonQtImportError = PyErr_NewException(const_cast("PythonQtImport.PythonQtImportError"), PyExc_ImportError, NULL); if (PythonQtImportError == NULL) return; @@ -808,7 +808,7 @@ void PythonQtImport::init() // set our importer into the path_hooks to handle all path on sys.path PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter"); - PyObject* path_hooks = PySys_GetObject("path_hooks"); + PyObject* path_hooks = PySys_GetObject(const_cast("path_hooks")); PyList_Append(path_hooks, classobj); #ifndef WIN32 diff --git a/src/PythonQtImporter.h b/src/PythonQtImporter.h index 196cf5b..a5d0f8c 100644 --- a/src/PythonQtImporter.h +++ b/src/PythonQtImporter.h @@ -42,7 +42,8 @@ */ //---------------------------------------------------------------------------------- -#include "Python.h" +#include "PythonQtPythonInclude.h" + #include "structmember.h" #include "osdefs.h" #include "marshal.h" diff --git a/src/PythonQtInstanceWrapper.h b/src/PythonQtInstanceWrapper.h index ded5867..761c844 100644 --- a/src/PythonQtInstanceWrapper.h +++ b/src/PythonQtInstanceWrapper.h @@ -42,7 +42,7 @@ */ //---------------------------------------------------------------------------------- -#include +#include "PythonQtPythonInclude.h" #include "PythonQtSystem.h" #include @@ -98,3 +98,4 @@ int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self); #endif + diff --git a/src/PythonQtObjectPtr.cpp b/src/PythonQtObjectPtr.cpp index f86eac4..f5518f0 100644 --- a/src/PythonQtObjectPtr.cpp +++ b/src/PythonQtObjectPtr.cpp @@ -41,6 +41,25 @@ #include +PythonQtObjectPtr::PythonQtObjectPtr(PyObject* o) +{ + _object = o; + if (o) Py_INCREF(_object); +} + +PythonQtObjectPtr::~PythonQtObjectPtr() +{ + if (_object) Py_DECREF(_object); +} + +void PythonQtObjectPtr::setNewRef(PyObject* o) +{ + if (o != _object) { + if (_object) Py_DECREF(_object); + _object = o; + } +} + QVariant PythonQtObjectPtr::evalScript(const QString& script, int start) { return PythonQt::self()->evalScript(_object, script, start); @@ -96,6 +115,14 @@ bool PythonQtObjectPtr::fromVariant(const QVariant& variant) else { setObject(0); return false; + } +} + +void PythonQtObjectPtr::setObject(PyObject* o) +{ + if (o != _object) { + if (_object) Py_DECREF(_object); + _object = o; + if (_object) Py_INCREF(_object); } - } diff --git a/src/PythonQtObjectPtr.h b/src/PythonQtObjectPtr.h index 6d5bf65..6fcc53f 100644 --- a/src/PythonQtObjectPtr.h +++ b/src/PythonQtObjectPtr.h @@ -42,7 +42,8 @@ */ //---------------------------------------------------------------------------------- -#include +#include "PythonQtPythonInclude.h" + #include "PythonQtSystem.h" #include #include @@ -53,7 +54,8 @@ class PYTHONQT_EXPORT PythonQtObjectPtr public: PythonQtObjectPtr():_object(NULL) {} - PythonQtObjectPtr(const PythonQtObjectPtr &p):_object(NULL) { + PythonQtObjectPtr(const PythonQtObjectPtr &p) + :_object(NULL) { setObject(p.object()); } @@ -62,13 +64,10 @@ public: fromVariant(variant); } - PythonQtObjectPtr(PyObject* o) { - _object = o; - if (o) Py_INCREF(_object); - } - - ~PythonQtObjectPtr() { if (_object) { Py_DECREF(_object); } } - + PythonQtObjectPtr(PyObject* o); + + ~PythonQtObjectPtr(); + //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count. bool fromVariant(const QVariant& variant); @@ -114,13 +113,8 @@ public: operator PyObject*() const { return object(); } //! sets the object and passes the ownership (stealing the reference, in Python slang) - void setNewRef(PyObject* o) { - if (o != _object) { - if (_object) { Py_DECREF(_object); } - _object = o; - } - } - + void setNewRef(PyObject* o); + PyObject* object() const { return _object; } @@ -155,14 +149,8 @@ public: protected: - void setObject(PyObject* o) { - if (o != _object) { - if (_object) { Py_DECREF(_object); } - _object = o; - if (_object) { Py_INCREF(_object); } - } - } - + void setObject(PyObject* o); + private: PyObject* _object; }; @@ -172,3 +160,4 @@ private: Q_DECLARE_METATYPE(PythonQtObjectPtr) #endif + diff --git a/src/PythonQtSignalReceiver.h b/src/PythonQtSignalReceiver.h index 49ac0dc..56d915a 100644 --- a/src/PythonQtSignalReceiver.h +++ b/src/PythonQtSignalReceiver.h @@ -42,7 +42,8 @@ */ //---------------------------------------------------------------------------------- -#include +#include "PythonQtPythonInclude.h" + #include "PythonQtSystem.h" #include "PythonQtObjectPtr.h" diff --git a/src/PythonQtSlot.cpp b/src/PythonQtSlot.cpp index b019b7e..401b54e 100644 --- a/src/PythonQtSlot.cpp +++ b/src/PythonQtSlot.cpp @@ -364,7 +364,7 @@ PythonQtSlotInfo* PythonQtSlotFunction_GetSlotInfo(PyObject *op) { if (!PythonQtSlotFunction_Check(op)) { - PyErr_BadInternalCall(); + PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__); return NULL; } return ((PythonQtSlotFunctionObject *)op) -> m_ml; @@ -374,7 +374,7 @@ PyObject * PythonQtSlotFunction_GetSelf(PyObject *op) { if (!PythonQtSlotFunction_Check(op)) { - PyErr_BadInternalCall(); + PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__); return NULL; } return ((PythonQtSlotFunctionObject *)op) -> m_self; @@ -439,9 +439,9 @@ meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/) } static PyGetSetDef meth_getsets [] = { - {"__doc__", (getter)meth_get__doc__, NULL, NULL}, - {"__name__", (getter)meth_get__name__, NULL, NULL}, - {"__self__", (getter)meth_get__self__, NULL, NULL}, + {const_cast("__doc__"), (getter)meth_get__doc__, NULL, NULL}, + {const_cast("__name__"), (getter)meth_get__name__, NULL, NULL}, + {const_cast("__self__"), (getter)meth_get__self__, NULL, NULL}, {NULL, NULL, NULL,NULL}, }; @@ -452,7 +452,7 @@ static PyGetSetDef meth_getsets [] = { #define OFF(x) offsetof(PythonQtSlotFunctionObject, x) static PyMemberDef meth_members[] = { - {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED}, + {const_cast("__module__"), T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED}, {NULL} }; diff --git a/src/PythonQtSlot.h b/src/PythonQtSlot.h index 4c7441a..d81ce70 100644 --- a/src/PythonQtSlot.h +++ b/src/PythonQtSlot.h @@ -42,7 +42,8 @@ */ //---------------------------------------------------------------------------------- -#include "Python.h" +#include "PythonQtPythonInclude.h" + #include "PythonQtSystem.h" #include "structmember.h" diff --git a/src/PythonQtStdDecorators.h b/src/PythonQtStdDecorators.h index 2b4f204..2d90af2 100644 --- a/src/PythonQtStdDecorators.h +++ b/src/PythonQtStdDecorators.h @@ -42,8 +42,10 @@ */ //---------------------------------------------------------------------------------- +#include "PythonQtPythonInclude.h" + #include "PythonQtSystem.h" -#include + #include #include #include diff --git a/src/PythonQtStdOut.cpp b/src/PythonQtStdOut.cpp index 1f5b040..053129f 100644 --- a/src/PythonQtStdOut.cpp +++ b/src/PythonQtStdOut.cpp @@ -87,8 +87,8 @@ static PyMethodDef PythonQtStdOutRedirect_methods[] = { }; static PyMemberDef PythonQtStdOutRedirect_members[] = { - {"softspace", T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0, - "soft space flag" + {const_cast("softspace"), T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0, + const_cast("soft space flag") }, {NULL} /* Sentinel */ }; diff --git a/src/PythonQtStdOut.h b/src/PythonQtStdOut.h index 59a2812..01724de 100644 --- a/src/PythonQtStdOut.h +++ b/src/PythonQtStdOut.h @@ -43,7 +43,8 @@ //---------------------------------------------------------------------------------- -#include +#include "PythonQtPythonInclude.h" + #include "structmember.h" #include diff --git a/src/gui/PythonQtScriptingConsole.h b/src/gui/PythonQtScriptingConsole.h index b208ac6..9b2571e 100644 --- a/src/gui/PythonQtScriptingConsole.h +++ b/src/gui/PythonQtScriptingConsole.h @@ -146,4 +146,5 @@ private: -#endif \ No newline at end of file +#endif +