Re: [PyQt] Fwd: Re: c++ app integrate PyQt
Hi, In case you are on M$-WIndows, I'd like to mention a nasty bug in Visual C++ 2012 that took me days to dig out of google: http://bugs.python.org/issue17797 In short: when you embedd the python interpreter into an application compiled as WINDOWS (not as CONSOLE), the operating system doesn't create stdin, stdout and stderr. They just don't exist, which is perfectly normal for a Windows GUI app. This is checked by Python. Older versions of the MS runtime lib correctly reported these streams missing. However, the runtime lib of VS2012 reports they exist even though they don't, which finally raises an exception and prevents Python from initializing. Microsoft knows: http://connect.microsoft.com/VisualStudio/feedback/details/785119/ It might be possible that mingw users also run into this issue because it relies on the MS runtime lib, too. Best Regards, Mathias On 02.10.2013, 03:11:39 John Fabiani wrote: Original Message Subject: Re: [PyQt] c++ app integrate PyQt Date: Mon, 30 Sep 2013 17:51:28 -0700 From: John Fabiani jo...@jfcomputer.com To: Matt Newell newe...@blur.com On 09/30/2013 05:24 PM, Matt Newell wrote: On Monday, September 30, 2013 04:51:24 PM John Fabiani wrote: Hi, ... someone have an example or a link explaining the details. Johnf ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] PyQt5 Snapshot, build problems and their solutions, Windows, mingw
On 07.07.2013, 15:13:15 Phil Thompson wrote: On Sun, 12 May 2013 22:42:23 +0200, mathias.b...@gmx.de wrote: Hi, I've compiled the latest PyQt5 snaphot, on 32bit python 3.3.1 (compiled with mingw, using a self-made build script based on scons), Windows7, Qt 5.1alpha. I've used this configuration step: D:\_cpp_projects_\Python\Python-3.3.1\.build_release\python.exe configure.py --no-docstrings --confirm-license -u --spec=win32-g++ --verbose --trace --sip=D:\_cpp_projects_\Python\Python-3.3.1\sip.exe LFLAGS+=-LD:\_cpp_projects_\Python\Python-3.3.1\.build_debug -LD:\_cpp_projects_\Python\Python-3.3.1\.build_release DEFINES+=_DEBUG (It's necessary to include the release version of the python lib even in debug build for the designer plugins.) I've run into a number of problems: (1) PyQt's configure.py autoamtically assumes certain MS-compilers on the win32 platform, in TargetConfiguration.__init__():262 and following: # The default qmake spec. if sys.platform == 'win32': if self.py_version = 0x030300: #self.qmake_spec = 'win32-msvc2010' self.qmake_spec = 'win32-g++' elif self.py_version = 0x020600: self.qmake_spec = 'win32-msvc2008' elif self.py_version = 0x020400: self.qmake_spec = 'win32-msvc.net' else: self.qmake_spec = 'win32-msvc' else: # Use the Qt default. (We may update it for MacOS/X later.) self.qmake_spec = '' I had to make the marked change to get around that for my mingw-based python. It would be nice if there was an option to influence that. I don't understand why this is needed. Using the --spec option should do that. [Motivation: I must embedd the python interpreter, and I want to get away from MS Visual Studio, because it is becoming slower with each version. Hence I'll have to compile python myself using mingw, which is non-standard.] (2) All makefiles attempt to build all DLLs without referring to the python DLL. Adding -lpython33_d to each Makefile.Debug and -lpython33 to Makefile.Release solves this. I tried adding LFLAGS_DEBUG+=-lpython33_d as parameter to the configure script, but it had no effect on the makefiles. (3) The final debugging versions of the DLLs get the wrong names. They all miss the trailing _d. This way they can't be imported, unless manually renamed arcordingly. Try tonight's snapshot. Thanks. Using VS2012, it now works out of the box with python 3.3.2 and Qt 5.1. Have not tested the mingw stuff yet. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] [SIP] is there a Qt5 example for SIP?
On 07.07.2013, 13:46:02 br...@stottlemyer.com wrote: On Sat, 6 Jul 2013 07:30:43 -0700, br...@stottlemyer.com wrote: Hi Phil, I am trying to see if SIP will help me with a task I'm trying to solve. I started out by trying the More Complex C++ Example in the docs. However, I'm using Qt5, and the example is for Qt4. I see the pyqtconfig is part of Qt4, but not Qt5. No problem, except pyqtconfig is pretty integrated into the example, and as a beginner, I'm not sure how to take pyqtconfig out. Is there a Qt5 example for SIP? Look at the configure.py for PyQt5. A minimal build system would just be a shell script that invoked sip then the C++ compiler then the linker. The only thing you need to consider is to use the right -t flags to sip and these can be found by introspecting current versions of PyQt. Phil Thanks for the pointers. I've got the example working. But now I'm having trouble extending the example. I've got a bunch of enums I need to make available, some of which have overlapping names. I've been handling this by putting them in different namespaces. But sip is complaining about that. I saw an old mailing list question on the topic (http://www.riverbankcomputing.com/pipermail/pyqt/2007-August/016847.html), but no solution was posted. My .h file is: // Define the interface to the hello library. #include qlabel.h #include qwidget.h #include qstring.h #if defined HELLO_DLL # define HELLO_DLLSPEC Q_DECL_EXPORT #else # define HELLO_DLLSPEC Q_DECL_IMPORT #endif namespace MyNamespace { enum MyEnum { No=0, Yes=1}; }; class HELLO_DLLSPEC Hello : public QLabel { // This is needed by the Qt Meta-Object Compiler. Q_OBJECT public: Hello(QWidget *parent = 0); private: // Prevent instances from being copied. Hello(const Hello ); Hello operator=(const Hello ); }; #if !defined(Q_OS_WIN) void setDefault(const QString def); #endif My .sip file is: // Define the SIP wrapper to the hello library. %Module hello %Import QtGui/QtGuimod.sip %Import QtWidgets/QtWidgetsmod.sip %If (Qt_5_0_0 -) namespace MyNamespace { %TypeHeaderCode #include hello.h %End enum MyEnum { No=0, Yes=1}; }; class Hello : public QLabel { %TypeHeaderCode #include hello.h %End public: Hello(QWidget *parent /TransferThis/ = 0); private: Hello(const Hello ); }; %If (!WS_WIN) void setDefault(const QString def); %End %End The compiler (linker, actually) is complaining about missing symbols: Creating library release\hello.lib and object release\hello.exp siphellocmodule.obj : error LNK2001: unresolved external symbol struct _pyqt4ClassTypeDef sipTypeDef_hello_MyNamespace (?sipTypeDef_hello_MyNamespace@@3U_pyqt4ClassTypeDef@@A) release\hello.dll : fatal error LNK1120: 1 unresolved externals What's the proper way to describe this to sip? Hi, Are you really compiling and linking all C++ files generated by SIP? Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
[PyQt] Bug: PyQt5.uic.loadUi() attempts to set non-existing property
Hi, There appears to be an error in the loading of .ui files in PyQt5. Please try the attached example. Error message: Traceback (most recent call last): File D:\eclipse.workspace\py_tests\src\uic_bug.py, line 15, in module window = LogWindow() File D:\eclipse.workspace\py_tests\src\uic_bug.py, line 8, in __init__ PyQt5.uic.loadUi(os.path.join(os.path.dirname(__file__), 'log_window.ui'), self) File D:\_cpp_projects_\Python\Python-3.3.1\lib\site-packages\PyQt5\uic\__init__.py, line 224, in loadUi return DynamicUILoader(package).loadUi(uifile, baseinstance, resource_suffix) File D:\_cpp_projects_\Python\Python-3.3.1\lib\site-packages\PyQt5\uic\Loader\loader.py, line 72, in loadUi return self.parse(filename, resource_suffix, basedir) File D:\_cpp_projects_\Python\Python-3.3.1\lib\site-packages\PyQt5\uic\uiparser.py, line 931, in parse actor(elem) File D:\_cpp_projects_\Python\Python-3.3.1\lib\site-packages\PyQt5\uic\uiparser.py, line 756, in createUserInterface self.traverseWidgetTree(elem) File D:\_cpp_projects_\Python\Python-3.3.1\lib\site-packages\PyQt5\uic\uiparser.py, line 734, in traverseWidgetTree handler(self, child) File D:\_cpp_projects_\Python\Python-3.3.1\lib\site-packages\PyQt5\uic\uiparser.py, line 444, in createLayout self.stack.push(self.setupObject(classname, parent, elem)) File D:\_cpp_projects_\Python\Python-3.3.1\lib\site-packages\PyQt5\uic\uiparser.py, line 161, in setupObject self.wprops.setProperties(obj, branch) File D:\_cpp_projects_\Python\Python-3.3.1\lib\site-packages\PyQt5\uic\properties.py, line 415, in setProperties getattr(widget, set%s%s % (ascii_upper(prop_name[0]), prop_name[1:]))(prop_value) AttributeError: 'QHBoxLayout' object has no attribute 'setMargin' The log_window.ui instantiates a QHBoxLayout, with all margins set to the same value. This makes the uic module try to set a margin property, which doesn't exist. Setting one of the margins (for example leftMargin) to a different value works. Best Regards, Mathias Born log_window.ui Description: Binary data from PyQt5.QtWidgets import * import PyQt5.uic, sys, os.path class LogWindow(QFrame): def __init__(self): QFrame.__init__(self) PyQt5.uic.loadUi(os.path.join(os.path.dirname(__file__), 'log_window.ui'), self) if __name__ == '__main__': import sys app = QApplication(sys.argv) window = LogWindow() window.show() app.exec_() ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
[PyQt] PyQt5 Snapshot, build problems and their solutions, Windows, mingw
Hi, I've compiled the latest PyQt5 snaphot, on 32bit python 3.3.1 (compiled with mingw, using a self-made build script based on scons), Windows7, Qt 5.1alpha. I've used this configuration step: D:\_cpp_projects_\Python\Python-3.3.1\.build_release\python.exe configure.py --no-docstrings --confirm-license -u --spec=win32-g++ --verbose --trace --sip=D:\_cpp_projects_\Python\Python-3.3.1\sip.exe LFLAGS+=-LD:\_cpp_projects_\Python\Python-3.3.1\.build_debug -LD:\_cpp_projects_\Python\Python-3.3.1\.build_release DEFINES+=_DEBUG (It's necessary to include the release version of the python lib even in debug build for the designer plugins.) I've run into a number of problems: (1) PyQt's configure.py autoamtically assumes certain MS-compilers on the win32 platform, in TargetConfiguration.__init__():262 and following: # The default qmake spec. if sys.platform == 'win32': if self.py_version = 0x030300: #self.qmake_spec = 'win32-msvc2010' self.qmake_spec = 'win32-g++' elif self.py_version = 0x020600: self.qmake_spec = 'win32-msvc2008' elif self.py_version = 0x020400: self.qmake_spec = 'win32-msvc.net' else: self.qmake_spec = 'win32-msvc' else: # Use the Qt default. (We may update it for MacOS/X later.) self.qmake_spec = '' I had to make the marked change to get around that for my mingw-based python. It would be nice if there was an option to influence that. [Motivation: I must embedd the python interpreter, and I want to get away from MS Visual Studio, because it is becoming slower with each version. Hence I'll have to compile python myself using mingw, which is non-standard.] (2) All makefiles attempt to build all DLLs without referring to the python DLL. Adding -lpython33_d to each Makefile.Debug and -lpython33 to Makefile.Release solves this. I tried adding LFLAGS_DEBUG+=-lpython33_d as parameter to the configure script, but it had no effect on the makefiles. (3) The final debugging versions of the DLLs get the wrong names. They all miss the trailing _d. This way they can't be imported, unless manually renamed arcordingly. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] General questions on parsing large QStrings
On 12.05.2013, 22:19:55 David Cortesi wrote: For an app to be built with PyQt5/Qt5, I will have a QPlainTextEdit in which the document may be quite sizable, 500K characters or more. I will want at times to inspect the document character by character, or possibly apply Python relib REs to it. I am somewhat at sea regarding the relationship between a const QString such as returned by QPlainTextEdit.toPlainText() and a Python3 unicode string, and -- just in general -- about the best way to do intensive examination of big strings. Is there a copy involved in, e.g. docstring = unicode( myEditor.toPlainText() ) I note that the PyQt4 QString reference omits the QString.begin() or .constBegin() etc methods that return an STL-style iterator so that's out. Is there some internal magic to integrate the QString type into Python's for mechanism so that for c in myEditor.toPlainText() might be more efficient than making a Python3 string and iterating on it? Also in regard to making intensive loops faster, how well do PyQtx calls integrate with Cython or PyPy? Thanks for any insights, Dave Cortesi Hi, This is how you cand find out things like this yourself: QPlainTextEdit.toPlainText() is wrapped in python dir\sip\PyQt5\QtWidgets\qplaintextedit.sip as QString toPlainText() const; QString is not wrapped normally as class, but defined as a mapped type in python dir\sip\PyQt5\QtCore\qstring.sip. The part interesting you is the conversion C++ - Python: %ConvertFromTypeCode return qpycore_PyObject_FromQString(*sipCpp); %End This function can be found in the source code of PyQt5: // Convert a QString to a Python Unicode object. PyObject *qpycore_PyObject_FromQString(const QString qstr) { PyObject *obj; #if defined(PYQT_PEP_393) obj = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, qstr.constData(), qstr.length()); #elif defined(Py_UNICODE_WIDE) QVectoruint ucs4 = qstr.toUcs4(); if ((obj = PyUnicode_FromUnicode(NULL, ucs4.size())) == NULL) return NULL; memcpy(PyUnicode_AS_UNICODE(obj), ucs4.constData(), ucs4.size() * sizeof (Py_UNICODE)); #else if ((obj = PyUnicode_FromUnicode(NULL, qstr.length())) == NULL) return NULL; memcpy(PyUnicode_AS_UNICODE(obj), qstr.utf16(), qstr.length() * sizeof (Py_UNICODE)); #endif return obj; } As you can see, this will use a lot of memory in your case. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] faulty PyQt 4.10 Makefile on Windows
On 21.04.2013, 10:58:11 Phil Thompson wrote: On Sun, 21 Apr 2013 01:10:01 +0200, mathias.b...@gmx.de wrote: Hi, Both, the latest stable PyQt 4.10 as well as PyQt-win-gpl-snapshot-4.10.1-66f4c96140c6.zip generate Makefiles with errors on my Windows machine. Instead of @if not exist D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 mkdir D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 I get @if not exist # legacy D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 mkdir # legacy D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 in the 'install' target. Then, Microsoft nmake complains. Manually removing all # legacy fixed it. But I couldn't figure out which of the build tools put it in there. That will come from Qt. Which version of Qt? Phil The official qt-everywhere-opensource-src-5.1.0-alpha.7z from http://qt-project.org/wiki/Qt-5.1-Alpha Compiled without errors. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] faulty PyQt 4.10 Makefile on Windows
On 21.04.2013, 11:37:50 Phil Thompson wrote: On Sun, 21 Apr 2013 11:25:15 +0200, mathias.b...@gmx.de wrote: On 21.04.2013, 10:58:11 Phil Thompson wrote: On Sun, 21 Apr 2013 01:10:01 +0200, mathias.b...@gmx.de wrote: Hi, Both, the latest stable PyQt 4.10 as well as PyQt-win-gpl-snapshot-4.10.1-66f4c96140c6.zip generate Makefiles with errors on my Windows machine. Instead of @if not exist D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 mkdir D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 I get @if not exist # legacy D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 mkdir # legacy D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 in the 'install' target. Then, Microsoft nmake complains. Manually removing all # legacy fixed it. But I couldn't figure out which of the build tools put it in there. That will come from Qt. Which version of Qt? Phil The official qt-everywhere-opensource-src-5.1.0-alpha.7z from http://qt-project.org/wiki/Qt-5.1-Alpha Compiled without errors. ...so a Qt bug. Phil I find that very strange. Are you saying that a Qt bug changes a Makefile in _your_ PyQt package where it attempts to copy the modules to ..\Lib\site-packages\PyQt4? Admittedly, I couldn't find the text # legacy anywhere in sip, nor in PyQt. Even if it is a Qt bug, would you not be interested in knowing more about it? It prevents building PyQt ... Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
[PyQt] faulty PyQt 4.10 Makefile on Windows
Hi, Both, the latest stable PyQt 4.10 as well as PyQt-win-gpl-snapshot-4.10.1-66f4c96140c6.zip generate Makefiles with errors on my Windows machine. Instead of @if not exist D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 mkdir D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 I get @if not exist # legacy D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 mkdir # legacy D:\_cpp_projects_\Python\Python-3.3.0\Lib\site-packages\PyQt4 in the 'install' target. Then, Microsoft nmake complains. Manually removing all # legacy fixed it. But I couldn't figure out which of the build tools put it in there. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] selecting a bezier curve
Hi, I'd like to point out that, realistically, the QGraphicsView framework is obsolete. Yes, it may still be around a while. But: The new OpenGL based QtQuick 2.0 graphics stack is way better. I'm in the process of porting a C++ application from QGraphicsView to QtQuick 2.0, which used a lot of custom QGraphicsItems which are now QQuickItems. The performance increase is unbelieveable. And it's more powerful and has more features, too! I was very sceptical at first, as this make me dependent on hardware accelerated OpenGL now. But in the year 2013 this is really no problem. Of course, right now QtQuick 2.0 is out of reach for PyQt users. But that will change. And the new model fits the Python approach much better. In QGraphicsView, Python code is run every time a frame is drawn. In QtQuick, your Python code generates a description of the scene once, which is then drawn by the 3D-chip exclusively. Very fast. Best Regards, Mathias Born On 14.04.2013, 02:15:16 Tom Brown wrote: I've created a simple application (see below) that draws a bezier curve. I want to give the user the ability to select the curve so they can move it around. However, I'm having trouble selecting the curve in an intuitive fashion. When I click on the curve, the point I click on is actually far away from the curve. ... ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
[PyQt] Bug report, compiling latest snapshots against Qt5 on Windows
Hi, I'm getting errors running PyQt's configure.py. Cause: Starting in line 954, the file sipconfig.py of the sip module contains: if sys.platform == win32 and shared in self.config.qt_winconfig.split(): if (mname in (QtCore, QtDeclarative, QtDesigner, QtGui, QtHelp, QtMultimedia, QtNetwork, QtOpenGL, QtScript, QtScriptTools, QtSql, QtSvg, QtTest, QtWebKit, QtXml, QtXmlPatterns, phonon) or (qt_version = 0x040200 and mname == QtAssistant)): lib = lib + 4 if sys.platform.startswith(linux) and qt_version = 0x05: lib = Qt5 + lib[2:] However, my Qt5 build created libraries named Qt5Gui.lib and so on, not QtGui4.lib. If I replace lib = lib + 4 by lib = Qt5 + lib[2:] I get the right library names, but then I get linker errors due to missing symbols from the Qt5Widgets.lib, which the script seems to miss as dependency. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
[PyQt] bug in pyqt's configure.py
Hi, In the latest snapshot (PyQt-win-gpl-snapshot-4.10-f0118624625e.zip), I noticed an error in its configure.py when run on Python 3.3. lines 1925 to 1931 read: # Qt5 doesn't have the 'default' link. if not os.path.isdir(fname): f = get_command_stdout(opts.qmake + -query QMAKE_SPEC) fname = f.read().strip() f.close() fname = os.path.join(qt_datadir, mkspecs, fname) The problem here is that fname = f.read().strip() creates a byte array, not a string, which makes fname = os.path.join(qt_datadir, mkspecs, fname) fail, because qt_datadir is a string. These possible fixes come to my mind: (1) Just add decode to the reading: fname = f.read().strip().decode() (2) Change function get_command_stdout in line 1401: p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=stderr, env=env, universal_newlines=True) However, this most likely will break other parts. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Help tracking down intermittent segfault using QGraphicsItem
Lee, I tried pynguin-0.12.zip on Windows7, python 2.7, PyQt 4.8.4 32bit, and I could run go() many times without any crashes or warnings. However, there appears to be no tournament function. One advise, if I may say so: The chance of finding someone who would be willing to debugg your entire project is slim. On a mailing list such as this one, the best way is to reduce the problem to a self contained, minimum size test case which reproduces the bug. Best Regards, Mathias Born On 05.01.2013, 05:11:10 Lee Harr wrote: I develop a free python turtle graphics application: http://pynguin.googlecode.com/ Right now I am trying to track down and fix an intermittent segfault involving a QGraphicsScene and QGraphicsItem Here is what I have... a QGraphicsItem subclass (item0) created with parent=None another QGraphicsItem subclass (item1) created with parent=item0 I then add item0 to my scene and things appear to be working fine, but when removing and adding instances of this arrangement in rapid succession I will soon get a segfault. If you want to play along at home, load the horserace.pyn example and run the tournament function. For me it will crash reliably within the first 2 or 3 races. In this case, item1 represents the text labels for the horses. If I remove the labels, I never see the segfault. The strangest part is that if I manually add item1 to the scene (should not be needed since the child is automatically added when the parent is added) I do not get the segfault. The only problem with this is that I get a warning: QGraphicsScene::addItem: item has already been added to this scene So... my questions: What is most likely to be the real problem here? How likely is it that if I get it to the point that there is no segfault on my machine (ie, just leave in the code that generates the warning) that it won't segfault on a different OS/architecture? What is the best way to go about tracking down and fixing the real problem? Thanks for any assistance. ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Help tracking down intermittent segfault using QGraphicsItem
On 05.01.2013, 16:50:29 Andreas Pakulat wrote: [...] Often a segfault is caused by using a pointer (in C++) which points to a memory location thats not valid anymore, for example because the object has been deleted already. In the context of PyQt this can happen when you stop keeping references to objects that or instances of C++-provided classes in python. In such a case the C++ parts of the object will be deleted and thus any other C++ code that has a reference to the object will crash when it tries to access the object. I think thats the most common problem one encounters with PyQt4. While this is certainly true in general, I'd say that sip goes to great length in order to avoid that kind of crash by carefully observing who owns what. It is aware of the parent-child memory management of Qt. A python program should never be able to cause a crash. Is there any place in PyQt where the Python code has to keep references to keep the program going? Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Help tracking down intermittent segfault using QGraphicsItem
On 05.01.2013, 22:58:28 Andreas Pakulat wrote: Hi, Am Samstag, 5. Januar 2013 schrieb : On 05.01.2013, 16:50:29 Andreas Pakulat wrote: [...] Often a segfault is caused by using a pointer (in C++) which points to a memory location thats not valid anymore, for example because the object has been deleted already. In the context of PyQt this can happen when you stop keeping references to objects that or instances of C++-provided classes in python. In such a case the C++ parts of the object will be deleted and thus any other C++ code that has a reference to the object will crash when it tries to access the object. I think thats the most common problem one encounters with PyQt4. While this is certainly true in general, I'd say that sip goes to great length in order to avoid that kind of crash by carefully observing who owns what. It is aware of the parent-child memory management of Qt. A python program should never be able to cause a crash. Is there any place in PyQt where the Python code has to keep references to keep the program going? Thats not always possible, it only works for objects which tell sip when they are deleted, for example QObject instances. Other Qt types do not support object life tracking like QObject, so sip has no way to know that it should not delete the object when the python reference is garbage collected. That's why you have to specify ownership in sip files and when using sip from the C++ side. sip doesn't actually track anything. If an object is owned by the Python side, the wrapped C++ part is destroyed when the reference count of the wrapper becomes zero. If it is owned by C++, the wrapper is deleted, but the C++ object stays alive. Erik Janssens posted this example: from PyQt4 import QtGui app = QtGui.QApplication([]) window = QtGui.QMainWindow() statusbar = window.statusBar() del window statusbar.objectName() which causes a crash in the last line, because window is gone along with the real (C++)statusbar, but the Python wrapper statusbar still exists without its C++ counterpart. That's because the QMainWindow instance is created by Python and thus owned by Python. In qmainwindow.sip: QStatusBar *statusBar() const /Transfer/; where /Transfer/ means: In the case of methods returned values (unless they are new references to already wrapped values) are normally owned by C++ anyway. However, in addition, an association between the returned value and the instance containing the method is created with regard to the cyclic garbage collector. (from the docs) If statusbar were given an extra reference to window, the crash could be avoided, but then del window would not delete the window anymore. This would be safer, but sip currently doesn't do that. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] A gobal variable problem in sip
On 24.10.2012, 00:11:13 D.Y Feng wrote: I meet a problem in my code: hello.h: #includeQtCore class Hello : public QObject{ Q_OBJECT public: Hello(QObject *parent = 0); static int test(){ static int i=0; qDebug()i++; return 0; } }; hello.cpp: #include hello.h const int i=Hello::test(); Hello::Hello (QObject *parent) { } hello.sip %Module hello %Import QtCore/QtCoremod.sip class Hello : public QObject { %TypeHeaderCode #include hello.h %End public: Hello(QObject *parent = 0); static int test(); }; I use the const int i=Hello::test(); to invoke test() before main function.It's uesful in factory pattern when you want to auto register driver. the python test code import hello hello.Hello.test1() It seems static int i in test() changed after import hello Now, I haven't tried that myself yet. On the other hand, I don't see any problem. Breakpoint 1, Hello::test1 () at hello.h:8 8 static int test1(){ (gdb) p i $1 = 0 (gdb) p i $2 = (const int *) 0x760300d0 This displays the address of your global variable const int i. (gdb) c Continuing. 0 Breakpoint 1, Hello::test1 () at main.h:8 8 static int test1(){ (gdb) p i $3 = (const int *) 0x760300d0 Again, address of your global variable const int i. (gdb) n 10 qDebug()i++; (gdb) p i $4 = (int *) 0x762355c0 ---What happen here? This shows the address of your local static variable static int i, which ought to be different. The names of these objects, which are both i, come into existence at different times. While this is perfectly legal C++, it obviously obfuscates your program. Just naming them differently should already help a lot. In summary, I don't think this is an issue with PyQt. But let me quote Bjarne Stroustrup: C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: add new annotation for specifying ownership of results of virtual methods
On 21.09.2012, 16:28:20 Phil Thompson wrote: On Mon, 3 Sep 2012 22:27:41 +0200, mathias.b...@gmx.de wrote: Hi Phil, I've come across a case which I think deserves its own function annotation. This is the proplem: I'm embedding Python code into a C++ app. There are two wrapped classes: class Netlister { virtual ~Netlister(); ... }; and class Project { virtual ~Project(); ... virtual NetLister* netLister(const std::string netListText) const; }; In Python, I have (ltse_app is the C++ app exposed as module) class LTspiceNetLister(ltse_app.NetLister): ... and class Project(ltse_app.Project): ... def netLister(self, netListText): return LTspiceNetLister() First, I call a Python function which gives me an instance of the Python class Project. Then (in C++, using its wrapper), I call its method netLister, which returns an instance of LTspiceNetLister. The goal is to use this instance on the C++ side via its wrapper. Thus, ownership should be with C++. But there is no corresponding annotation for the sip file. I have to provide a %VirtualCatcherCode: virtual NetLister* netLister(const std::string netListText /NoCopy/) const; %VirtualCatcherCode PyObject *resObj = sipCallMethod(0, sipMethod, D, const_caststd::string*(a0), sipType_std_string, NULL); sipIsErr = !resObj || sipParseResult(0, sipMethod, resObj, H0, sipType_NetLister, sipRes) 0; if (!sipIsErr) sipTransferTo(resObj, Py_None); Py_XDECREF(resObj); %End Note how I use sipTransferTo(resObj, Py_None); to bind the Python object to the C++ instance. I'm basically asking for something like the Factory annotation which does just that. Factory tells sip that a wrapped C++ function creates a new object that will be owned by the Python side. I'd like to have another annotation which tells sip that the Python implementation of a class method creates a new object that will be owned by the C++ side. The documentation for /Factory/ is wrong (now fixed in hg). It effectively does... sipTransferTo(resObj, selfObj); ...in the virtual catcher (where selfObj) is the class's self object (the Project instance in this case). You are using Py_None but I don't think it would make a difference. Would this remove your use case for sipTransfer(obj, Py_None)? Phil No it wouldn't. My embedding currently works like this: I have a .py file which is imported as module at program start. This module defines a factory function, which is called from C++ and returns an instance of a Python class derived from a sip-wrapped C++ class (Project). The PyObject* obtained this way is then fed into sip's api_convert_to_type to get hold of the wrapper instance. This instance is then used in the C++ code. It transparently forwards method calls to the Python part. (That's why it was so important to have the wrapper re-throw Python exceptions as C++ exceptions.) Thanks to sipTransfer(obj, Py_None) I don't have to manually manage the PyObject representing the Python part. It just gets automatically deleted by the C++ wrapper. Further, your sipTransferTo(resObj, selfObj); above would bind the returned NetLister to the Project instance. But they are not related in terms of life time. I only want the reference count of the Python part to be decreased by one when the C++ wrapper is destroyed. Provided there are no further references on the Python side, this automatically destroys the Python part, too. No parent-child relationships here like in Qt. Just Python objects that can be used in C++ as if they were C++ only. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: template %MappedType doesn't allow /AllowNone/
On 19.09.2012, 22:19:45 mathias.b...@gmx.de wrote: On 18.09.2012, 11:02:34 Phil Thompson wrote: A thought... Did you update from hg or use a snapshot? If hg did you change to the default branch? Phil I had not changed the branch. Now I have, and hg identify says 6d704a7ab6c5 tip. But now sip.exe crashes with my sip file. Don't have time right now to look at it, though. Best Regards, Mathias Born I believe you need to add spec-errorhandlers = NULL; to the parse function in parser.y of sipgen (line 4326). This stops sip.exe from crashing for me. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: extend exception support
On 19.09.2012, 11:07:14 Phil Thompson wrote: On Mon, 17 Sep 2012 22:25:59 +0200, mathias.b...@gmx.de wrote: On 17.09.2012, 22:14:49 Phil Thompson wrote: On Mon, 27 Aug 2012 12:10:23 -0700, Matt Newell newe...@blur.com wrote: The difference is the access to the (not necessarily present) objects. How are you getting these? Phil Here's the patch against a quite old hg checkout. After several more iterations (ok, rewrites) the implementation in the current snapshot should be Ok - and work with %Imported modules. Phil I'm pleased to report that this works fine for me. Some comments: In the docs about the %DefaultVirtualErrorHandler directive, there is a typo %DefaultVirtualErrorHandle my_handler which should read %DefaultVirtualErrorHandler my_handler In addition, the function type is not void my_handler(sip_gilstate_t, PyObject *); but instead void my_handler(sip_gilstate_t, sipSimpleWrapper*); You need to use the default branch (or a snapshot) - I changed it all again. Ok, but that's not working properly anymore. sip.h declares typedef void (*sipVirtErrorHandlerFunc)(struct _sipSimpleWrapper *); but the generated code containes error handlers that look like void sipVEH_ltse_app_defaultVirtualErrorHandler(sip_gilstate_t, PyObject *) And inside other functions they are referred to as, for example extern void sipVEH_ltse_app_defaultVirtualErrorHandler(sip_gilstate_t, PyObject *); Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: template %MappedType doesn't allow /AllowNone/
On 18.09.2012, 11:02:34 Phil Thompson wrote: A thought... Did you update from hg or use a snapshot? If hg did you change to the default branch? Phil I had not changed the branch. Now I have, and hg identify says 6d704a7ab6c5 tip. But now sip.exe crashes with my sip file. Don't have time right now to look at it, though. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: template %MappedType doesn't allow /AllowNone/
On 17.09.2012, 18:44:19 Phil Thompson wrote: On Mon, 10 Sep 2012 23:31:20 +0200, mathias.b...@gmx.de wrote: Phil, While using /AlloNone/ on a normal mapped type directive like %MappedType boost::optionalfs::path /AllowNone/ works, sip tells me Deprecation warning : type_mappings.sip.h:269: Annotation is invalid for templateType %MappedType boost::optionalType /AllowNone/ If this is intended, why this limitiation? Lazy programming on my part - fixed in hg. Phil I finally got around updating, but I still get the same error message. Best Regards, Mathias ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: extend exception support
On 17.09.2012, 22:14:49 Phil Thompson wrote: On Mon, 27 Aug 2012 12:10:23 -0700, Matt Newell newe...@blur.com wrote: The difference is the access to the (not necessarily present) objects. How are you getting these? Phil Here's the patch against a quite old hg checkout. After several more iterations (ok, rewrites) the implementation in the current snapshot should be Ok - and work with %Imported modules. Phil I'm pleased to report that this works fine for me. Some comments: In the docs about the %DefaultVirtualErrorHandler directive, there is a typo %DefaultVirtualErrorHandle my_handler which should read %DefaultVirtualErrorHandler my_handler In addition, the function type is not void my_handler(sip_gilstate_t, PyObject *); but instead void my_handler(sip_gilstate_t, sipSimpleWrapper*); Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: template %MappedType doesn't allow /AllowNone/
On 13.09.2012, 18:44:19 Phil Thompson wrote: On Mon, 10 Sep 2012 23:31:20 +0200, mathias.b...@gmx.de wrote: Phil, While using /AlloNone/ on a normal mapped type directive like %MappedType boost::optionalfs::path /AllowNone/ works, sip tells me Deprecation warning : type_mappings.sip.h:269: Annotation is invalid for templateType %MappedType boost::optionalType /AllowNone/ If this is intended, why this limitiation? Lazy programming on my part - fixed in hg. Phil Great, thanks! Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
[PyQt] sip: template %MappedType doesn't allow /AllowNone/
Phil, While using /AlloNone/ on a normal mapped type directive like %MappedType boost::optionalfs::path /AllowNone/ works, sip tells me Deprecation warning : type_mappings.sip.h:269: Annotation is invalid for templateType %MappedType boost::optionalType /AllowNone/ If this is intended, why this limitiation? Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
[PyQt] sip: add new annotation for specifying ownership of results of virtual methods
Hi Phil, I've come across a case which I think deserves its own function annotation. This is the proplem: I'm embedding Python code into a C++ app. There are two wrapped classes: class Netlister { virtual ~Netlister(); ... }; and class Project { virtual ~Project(); ... virtual NetLister* netLister(const std::string netListText) const; }; In Python, I have (ltse_app is the C++ app exposed as module) class LTspiceNetLister(ltse_app.NetLister): ... and class Project(ltse_app.Project): ... def netLister(self, netListText): return LTspiceNetLister() First, I call a Python function which gives me an instance of the Python class Project. Then (in C++, using its wrapper), I call its method netLister, which returns an instance of LTspiceNetLister. The goal is to use this instance on the C++ side via its wrapper. Thus, ownership should be with C++. But there is no corresponding annotation for the sip file. I have to provide a %VirtualCatcherCode: virtual NetLister* netLister(const std::string netListText /NoCopy/) const; %VirtualCatcherCode PyObject *resObj = sipCallMethod(0, sipMethod, D, const_caststd::string*(a0), sipType_std_string, NULL); sipIsErr = !resObj || sipParseResult(0, sipMethod, resObj, H0, sipType_NetLister, sipRes) 0; if (!sipIsErr) sipTransferTo(resObj, Py_None); Py_XDECREF(resObj); %End Note how I use sipTransferTo(resObj, Py_None); to bind the Python object to the C++ instance. I'm basically asking for something like the Factory annotation which does just that. Factory tells sip that a wrapped C++ function creates a new object that will be owned by the Python side. I'd like to have another annotation which tells sip that the Python implementation of a class method creates a new object that will be owned by the C++ side. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: how to make a python instance owned by C++ without using a parent
On 27.08.2012, 22:50:43 Phil Thompson wrote: On Sun, 26 Aug 2012 21:11:50 +0200, mathias.b...@gmx.de wrote: On 26.08.2012, 18:15:55 Phil Thompson wrote: On Wed, 15 Aug 2012 11:55:47 +0200, mathias.b...@gmx.de wrote: On 15.08.2012, 11:05:42 Phil Thompson wrote: I could change sipTransferTo() to do this if the owner was Py_None. At the moment this is undocumented behaviour. Would this be sufficient? I believe so. Done in hg. Phil, First tests show that this works well. It's an important feature, but burried deeply in the documentation, well, actually sort of obscured. Function sipConvertToType is documented as: If transferObj is NULL then the ownership is unchanged. If it is Py_None then ownership is transferred to Python via a call to sipTransferBack(). Otherwise ownership is transferred to C/C++ and obj associated with transferObj via a call to sipTransferTo(). Function sipTransferTo tells us: ... If owner is Py_None then obj is given an extra reference which is removed when the C++ instance’s destructor is called. ... Since sipTransferTo is mentioned by the docs of sipConvertToType, who would guess that Py_None has such a different meaning? How about adding a corresponding hint to the documentation of sipConvertToType? I'm not sure that adding documentation to something about what it doesn't do makes anything clearer. Phil That's because you are far too familiar with sip :-) I imagine adding something like Note that obj can also be managed by the C++ instance itself, but this can only be achieved by using sipTransferTo. to the documentation of sipConvertToType. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: extend exception support
On 27.08.2012, 14:34:10 Phil Thompson wrote: On Sun, 26 Aug 2012 22:22:40 +0200, mathias.b...@gmx.de wrote: On 26.08.2012, 16:07:52 Phil Thompson wrote: On Sun, 26 Aug 2012 14:30:32 +0200, mathias.b...@gmx.de wrote: On 26.08.2012, 16:46:24 Phil Thompson wrote: On Wed, 15 Aug 2012 15:54:11 +0200, mathias.b...@gmx.de wrote: ... Should all be fixed in current hg and tonight's snapshot. Thanks, Phil Ok, I pulled from the hg and could build everything. Quite nifty. One can now use class instances implemented in python just like normal C++ without any additional worries. One issue though. Discussions like http://www.boost.org/community/error_handling.html suggest that SIPPyException should be derived from std::exception. My original suggestion was a bit short-sighted. It would be even better to let the user define his own exception class. I'm using sip to embed python code into a Qt/C++ program. Every exception is reported to the user via a message box: catch(std::exception const exc) { QMessageBox(QMessageBox::Critical, Error, exc.what(), QMessageBox::Ok).exec(); } With SIPPyException the way it is, I need to add another exception handler everywhere: catch(SIPPyException const) { QMessageBox(QMessageBox::Critical, Error, pythonExceptionToText(), QMessageBox::Ok).exec(); } If I could provide a function to call instead of just doing throw SIPPyException(), I could throw an exception there myself as I see fit. For example, there could be a directive %MethodErrorHandlerCode throw std::runtime_error(pythonExceptionToText()); %End which would follow the %Module directive to define the body of an error handler function which is called instead of throw SIPPyException(). Best Regards, Mathias In current hg... %VirtualErrorCode is a new sub-directive of the %Module directive. all_throw_cpp_exception replaced by all_use_VirtualErrorCode. /ThrowsCppException/ replaced by /UsesVirtualErrorCode/. /NoThrowsCppException/ replaced by /NoUsesVirtualErrorCode/. Removed SIPPyException. Phil Great! I tested this, works fine. Thank you for providing this feature. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: extend exception support
On 26.08.2012, 16:46:24 Phil Thompson wrote: On Wed, 15 Aug 2012 15:54:11 +0200, mathias.b...@gmx.de wrote: Phil, sip can already propagate C++ exceptions into Python in cases where Python calls a C++ function which throws an exception. However, if I extend a C++ class in Python and call a corresponding (Python-)method in C++ via the wrapper, the sip generated wrapper code checks for a Python exception, but doesn't throw an excpetion itself. For example: = code generated by sip === boost::optionalint sipVH_ltse_app_0(sip_gilstate_t sipGILState,PyObject *sipMethod,const std::string a0) { boost::optionalint sipRes; PyObject *resObj = sipCallMethod(0,sipMethod,N,new std::string(a0),sipType_std_string,NULL); if (!resObj || sipParseResult(0,sipMethod,resObj,H5,sipType_boost_optional_1800,sipRes) 0) PyErr_Print(); Py_XDECREF(resObj); Py_DECREF(sipMethod); SIP_RELEASE_GIL(sipGILState) return sipRes; } = Here, PyErr_Print is called if the Python implementation of the method raises an exception. This is fine for Qt which cannot deal with exceptions, but in general I would find it much more helpful if the wrapper code generated by sip threw a C++ exception itself to signal the problem to the caller. Just define a class, e.g. SIPPyException (derived from std::exception), which becomes part of the API and is always used in such cases. In order not to break existing code, it would only be used in classes or methods which are annotated appropriately. (So an additional annotation is necessary to activate this behavior.) I believe an extension like this would make sip a lot more useful for embedding Python into a C++ program. Best Regards, Mathias Born Try current hg or tonight's snapshot. See the all_throw_cpp_exception %Module argument and the /ThrowsCppException/ and /NoThrowsCppException/ function annotations. Not heavily tested. That's great! I tried sip-4.13.4-snapshot-5f97352e818f.zip. When buidling sip, my MSVC2010 complains: sip.h(347) : error C2016: C requires that a struct or union has at least one member Possible fix: just change struct SIPPyException {}; to #ifdef __cplusplus struct SIPPyException {}; #endif That should be ok because it's for an exception, a C++ only feature. The generated code, for example: = code generated by sip === std::string sipVH_ltse_app_1(sip_gilstate_t sipGILState,PyObject *sipMethod,const std::string a0) { std::string sipRes; PyObject *resObj = sipCallMethod(0,sipMethod,N,new std::string(a0),sipType_std_string,NULL); if (!resObj || sipParseResult(0,sipMethod,resObj,H5,sipType_std_string,sipRes) 0) throw SIPPyException(); Py_XDECREF(resObj); Py_DECREF(sipMethod); SIP_RELEASE_GIL(sipGILState) return sipRes; } = will leak memory, though. All the Py_XDECREF(resObj); Py_DECREF(sipMethod); SIP_RELEASE_GIL(sipGILState) won't be executed in case of an exception. In addition, I get a lot of compilation errors when I try to build PyQt v4.9.4 with this new sip, for example: .\sipQtGuiQFontDialog.cpp(3298) : error C2664: 'void QFontDialog::open(QObject *,const char *)' : cannot convert parameter 1 from 'QObject **' to 'QObject *' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast That's a show stopper, as my stuff can't do without PyQT ... Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: extend exception support
On 26.08.2012, 16:07:52 Phil Thompson wrote: On Sun, 26 Aug 2012 14:30:32 +0200, mathias.b...@gmx.de wrote: On 26.08.2012, 16:46:24 Phil Thompson wrote: On Wed, 15 Aug 2012 15:54:11 +0200, mathias.b...@gmx.de wrote: ... Should all be fixed in current hg and tonight's snapshot. Thanks, Phil Ok, I pulled from the hg and could build everything. Quite nifty. One can now use class instances implemented in python just like normal C++ without any additional worries. One issue though. Discussions like http://www.boost.org/community/error_handling.html suggest that SIPPyException should be derived from std::exception. My original suggestion was a bit short-sighted. It would be even better to let the user define his own exception class. I'm using sip to embed python code into a Qt/C++ program. Every exception is reported to the user via a message box: catch(std::exception const exc) { QMessageBox(QMessageBox::Critical, Error, exc.what(), QMessageBox::Ok).exec(); } With SIPPyException the way it is, I need to add another exception handler everywhere: catch(SIPPyException const) { QMessageBox(QMessageBox::Critical, Error, pythonExceptionToText(), QMessageBox::Ok).exec(); } If I could provide a function to call instead of just doing throw SIPPyException(), I could throw an exception there myself as I see fit. For example, there could be a directive %MethodErrorHandlerCode throw std::runtime_error(pythonExceptionToText()); %End which would follow the %Module directive to define the body of an error handler function which is called instead of throw SIPPyException(). Best Regards, Mathias ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: how to make a python instance owned by C++ without using a parent
On 15.08.2012, 11:05:42 Phil Thompson wrote: On Tue, 14 Aug 2012 23:47:51 +0200, mathias.b...@gmx.de wrote: Thanks for the answer. However, it appears I've not made myself clear enough. I don't want the C++ wrapper to be owned by Python; surely, I can achieve that with sipTransferTo. But nothing is done about the Python part. When I delete the wrapper in C++, the Python part it wraps stays alive, because its reference count is not touched. (No parent!) I have to manually, explicitely decrease the reference count to get rid of it. I'm not complaining. I get this Python object from a Python function, so I have to take care of it. However, the sip module already contains some code that essentially already would do what I want: siplib.c === void sip_api_common_dtor(sipSimpleWrapper *sipSelf) { if (sipSelf != NULL sipInterpreter != NULL) { PyObject *xtype, *xvalue, *xtb; SIP_BLOCK_THREADS /* We may be tidying up after an exception so preserve it. */ PyErr_Fetch(xtype, xvalue, xtb); callPyDtor(sipSelf); PyErr_Restore(xtype, xvalue, xtb); sipOMRemoveObject(cppPyMap, sipSelf); /* This no longer points to anything useful. */ clear_access_func(sipSelf); /* * If C/C++ has a reference (and therefore no parent) then remove it. * Otherwise remove the object from any parent. */ if (sipCppHasRef(sipSelf)) { sipResetCppHasRef(sipSelf); Py_DECREF(sipSelf); } else if (PyObject_TypeCheck((PyObject *)sipSelf, (PyTypeObject *)sipWrapper_Type)) removeFromParent((sipWrapper *)sipSelf); SIP_UNBLOCK_THREADS } } = What about: if (sipCppHasRef(sipSelf)) { sipResetCppHasRef(sipSelf); Py_DECREF(sipSelf); } Is there an official way for my wrapper to have the SIP_CPP_HAS_REF flag set? It would then automatically dispose its Python counterpart. I could change sipTransferTo() to do this if the owner was Py_None. At the moment this is undocumented behaviour. Would this be sufficient? I believe so. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
[PyQt] sip: extend exception support
Phil, sip can already propagate C++ exceptions into Python in cases where Python calls a C++ function which throws an exception. However, if I extend a C++ class in Python and call a corresponding (Python-)method in C++ via the wrapper, the sip generated wrapper code checks for a Python exception, but doesn't throw an excpetion itself. For example: = code generated by sip === boost::optionalint sipVH_ltse_app_0(sip_gilstate_t sipGILState,PyObject *sipMethod,const std::string a0) { boost::optionalint sipRes; PyObject *resObj = sipCallMethod(0,sipMethod,N,new std::string(a0),sipType_std_string,NULL); if (!resObj || sipParseResult(0,sipMethod,resObj,H5,sipType_boost_optional_1800,sipRes) 0) PyErr_Print(); Py_XDECREF(resObj); Py_DECREF(sipMethod); SIP_RELEASE_GIL(sipGILState) return sipRes; } = Here, PyErr_Print is called if the Python implementation of the method raises an exception. This is fine for Qt which cannot deal with exceptions, but in general I would find it much more helpful if the wrapper code generated by sip threw a C++ exception itself to signal the problem to the caller. Just define a class, e.g. SIPPyException (derived from std::exception), which becomes part of the API and is always used in such cases. In order not to break existing code, it would only be used in classes or methods which are annotated appropriately. (So an additional annotation is necessary to activate this behavior.) I believe an extension like this would make sip a lot more useful for embedding Python into a C++ program. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: how to make a python instance owned by C++ without using a parent
On 15.08.2012, 18:15:55 Phil Thompson wrote: On Wed, 15 Aug 2012 11:55:47 +0200, mathias.b...@gmx.de wrote: On 15.08.2012, 11:05:42 Phil Thompson wrote: I could change sipTransferTo() to do this if the owner was Py_None. At the moment this is undocumented behaviour. Would this be sufficient? I believe so. Done in hg. Phil Thanks! Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] sip: how to make a python instance owned by C++ without using a parent
Thanks for the answer. However, it appears I've not made myself clear enough. I don't want the C++ wrapper to be owned by Python; surely, I can achieve that with sipTransferTo. But nothing is done about the Python part. When I delete the wrapper in C++, the Python part it wraps stays alive, because its reference count is not touched. (No parent!) I have to manually, explicitely decrease the reference count to get rid of it. I'm not complaining. I get this Python object from a Python function, so I have to take care of it. However, the sip module already contains some code that essentially already would do what I want: siplib.c === void sip_api_common_dtor(sipSimpleWrapper *sipSelf) { if (sipSelf != NULL sipInterpreter != NULL) { PyObject *xtype, *xvalue, *xtb; SIP_BLOCK_THREADS /* We may be tidying up after an exception so preserve it. */ PyErr_Fetch(xtype, xvalue, xtb); callPyDtor(sipSelf); PyErr_Restore(xtype, xvalue, xtb); sipOMRemoveObject(cppPyMap, sipSelf); /* This no longer points to anything useful. */ clear_access_func(sipSelf); /* * If C/C++ has a reference (and therefore no parent) then remove it. * Otherwise remove the object from any parent. */ if (sipCppHasRef(sipSelf)) { sipResetCppHasRef(sipSelf); Py_DECREF(sipSelf); } else if (PyObject_TypeCheck((PyObject *)sipSelf, (PyTypeObject *)sipWrapper_Type)) removeFromParent((sipWrapper *)sipSelf); SIP_UNBLOCK_THREADS } } = What about: if (sipCppHasRef(sipSelf)) { sipResetCppHasRef(sipSelf); Py_DECREF(sipSelf); } Is there an official way for my wrapper to have the SIP_CPP_HAS_REF flag set? It would then automatically dispose its Python counterpart. Best Regards, Mathias Born On 14.08.2012, 10:22:26 Phil Thompson wrote: On Mon, 13 Aug 2012 23:07:07 +0200, mathias.b...@gmx.de wrote: Hi, I have a C++ class Project, which I expose to Python via sip. In Python, I sub-class: class Derived(Project): ... In addition, there is a Python factory function which creates an instance of Derived and returns it: def f(): return Derived(...) I call this function from withing C++, and feed the return value into sipConvertToType, in order to create a wrapper of type Project, so I can call methods of the returned Derived instance from within C++, using the wrapper. Since the Derived instance is created by Python, it is owned by Python. Is there a way to transfer ownership to C++ without using any additional objects? I want the Python part to stick to the C++ wrapper until the latter is destroyed, at which point the Python part should also be automatically disposed, without any need to micro-manage the Python part myself. That will happen automatically anyway so long as Derived has a virtual dtor. The Python object will only ever be destroyed when its reference count reaches 0, irrespective of the state of the C++ instance. In the sip sources, I can see a flag SIP_CPP_HAS_REF that might just achieve that, but there appears to be no official way to use it. To transfer ownership of a Python object to C++ (ie. to control whether the Python dealloc code calls the C++ dtor) use... http://www.riverbankcomputing.com/static/Docs/sip4/c_api.html#sipTransferTo Phil ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
[PyQt] sip: how to make a python instance owned by C++ without using a parent
Hi, I have a C++ class Project, which I expose to Python via sip. In Python, I sub-class: class Derived(Project): ... In addition, there is a Python factory function which creates an instance of Derived and returns it: def f(): return Derived(...) I call this function from withing C++, and feed the return value into sipConvertToType, in order to create a wrapper of type Project, so I can call methods of the returned Derived instance from within C++, using the wrapper. Since the Derived instance is created by Python, it is owned by Python. Is there a way to transfer ownership to C++ without using any additional objects? I want the Python part to stick to the C++ wrapper until the latter is destroyed, at which point the Python part should also be automatically disposed, without any need to micro-manage the Python part myself. In the sip sources, I can see a flag SIP_CPP_HAS_REF that might just achieve that, but there appears to be no official way to use it. Best Regards, Mathias Born ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt