[PyKDE] Incorrect line numbers in compiler error messages
As I can see sip removes empty line when generating .cpp files. This causes incorrect line numbers in error messages from compiler calculated from values in #line directives. -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
[PyKDE] Bug in code for wrapped attributes
Below is a code generated for wrapped attribute (PyObject* in original class, SIP_PYOBJECT in SIP spec): --8-- static PyObject *var_MyClass_myAttr(PyObject *sipSelf,PyObject *sipPy) { PyObject * sipVal; MyClass *sipCpp = reinterpret_castMyClass *(sipGetCppPtr((sipWrapper *)sipSelf,sipClass_MyClass)); if (!sipCpp) return NULL; if (sipPy == NULL) { sipVal = sipCpp - myAttr; Py_XINCREF(sipVal); return sipVal; } sipVal = sipPy; if (PyErr_Occurred() != NULL) { sipBadSetType(sipNm_MyModule_MyClass,sipNm_MyModule_myAttr); return NULL; } Py_INCREF(sipVal); // -- missed increment sipCpp - myAttr = sipVal; Py_INCREF(Py_None); return Py_None; } --8-- There is no line marked with missed increment in generated code, so attribute value has incorrect reference count causing strange behavior and/or segmentation fault. The story about how I discovered this bug is quite interesting. I've written test script looking like the following: foo = MyModule.Foo() foo.myAttr = lambda *args: args bar = foo.createBar() # bar constructor assignes foo.myAttr to bar.myAttr def newMyAttr(*args): print 'newMyAttr called with', args bar.doSmth() # this method calls bar.myAttr I defined newMyAttr as replacement for earlier assigned function. Then I run the script and so expected output newMyAttr called with (2, 1, 2). Just a minute later I discovered that I'd actually forgotten to assign newMyAttr to bar.myAttr! Then why it's called?! Did Python conjectured that I wanted to assign newMyAttr itself? Looked like a mistery. I added print bar.myAttr before and after newMyAttr definition and saw: converter: function lambda at 0x30c994 converter: function newMyAttr at 0x30c994 Hey, these objects have the same address! Farther experiments proved my guess that lambda object was destroyed. In fact, after changing foo.myAttr = lambda *args: args into f = lambda *args: args foo.myAttr = f the problem disappeared. Putting print sys.getrefcount(f) showed 2 when 3 expected (f itself, foo.myAttr, and argument to getrefcount). -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] Handling exceptions in SIP
On Thu, 30 Jun 2005 17:24:27 +0100 Phil Thompson [EMAIL PROTECTED] wrote: 4) There are several standard exceptions which I always have to catch. Now I have a macro for them: #define CATCH_STD_EXCEPTIONS \ catch (std::bad_alloc) {\ PyErr_NoMemory(); \ sipIsErr = 1; \ } catch (std::exception exc) {\ PyErr_SetString(PyExc_RuntimeError, exc.what()); \ sipIsErr = 1; \ } catch (...) {\ PyErr_SetString(PyExc_RuntimeError, unknown); \ sipIsErr = 1; \ } used in %MethodCode: %MethodCode try { sipRes = someMethod(...); } CATCH_STD_EXCEPTIONS // sipIsErr - this comment is important hint to SIP! %End If your point is the need for the comment, then yes - consider it a feature. No, I meant these exceptions must be caught almost everywhere. So I have to add %MethodCode to almost every method, which is annoying. The latest release of SIP always catch all exceptions with catch(...) clause with -e option, but now it doesn't. -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] Handling exceptions in SIP
On Thu, 30 Jun 2005 17:24:27 +0100 Phil Thompson [EMAIL PROTECTED] wrote: 1) If sipExceptionRef is not used in RaiseCode we'll get a warning. Tonight's snapshot will only generate it if it is used. Now I get no sipExceptionRef in catch clause even when it's used in %RaiseCode. -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] Handling exceptions in SIP
On Fri, 1 Jul 2005 08:54:19 +0100 Phil Thompson [EMAIL PROTECTED] wrote: Whoops. Change the argument to the strstr() call that checks for sipExceptionRef from... xd-raisecode ...to... xd-raisecode-frag Now it works fine, thanks. -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] Handling exceptions in SIP
On Fri, 1 Jul 2005 17:37:44 +0100 Phil Thompson [EMAIL PROTECTED] wrote: If we solve the problem of how to specify ... then you could define std::bad_alloc, std::exception, and (somehow) ... using %Exception and then... void foo() throw (std::bad_alloc, std::exception, ...); If this is too much trouble, then I can only suggest implementing something like %DefaultExceptionHandler than contains your code and is applied to anything that has no throw specifier (so long as the -e option is used). I think we need some more feedback from other SIP users before going farther. -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] Handling exceptions in SIP
On Wed, 29 Jun 2005 15:59:08 +0100 Phil Thompson [EMAIL PROTECTED] wrote: sip command passes without error, but I have an error when linking: $OFILES in Makefile contains sipMyModuleMyException.o, while there is no corresponding .cpp file generated. BTW, when I use throw specifier in method signature without corresponding %Exception directive, sip exits with non-zero code, but reports no error message. All tests were done with sip-snapshot-20050626. Should be fixed in tonight's snapshot. Simple examples work like a charm with sip-snapshot-20050629, thanks! There are some points to discuss: 1) If sipExceptionRef is not used in RaiseCode we'll get a warning. 2) Exceptions that were not specified in throw are not caught and I see no way to add catch(...) to generated code. 3) throw specifier has no effect on generated code when %MethodCode is used, shouldn't it? 4) There are several standard exceptions which I always have to catch. Now I have a macro for them: #define CATCH_STD_EXCEPTIONS \ catch (std::bad_alloc) {\ PyErr_NoMemory(); \ sipIsErr = 1; \ } catch (std::exception exc) {\ PyErr_SetString(PyExc_RuntimeError, exc.what()); \ sipIsErr = 1; \ } catch (...) {\ PyErr_SetString(PyExc_RuntimeError, unknown); \ sipIsErr = 1; \ } used in %MethodCode: %MethodCode try { sipRes = someMethod(...); } CATCH_STD_EXCEPTIONS // sipIsErr - this comment is important hint to SIP! %End -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] Handling exceptions in SIP
On Sun, 26 Jun 2005 23:05:33 +0100 Phil Thompson [EMAIL PROTECTED] wrote: Support for this is in tonight's snapshot - some changes to what I described above, but nothing sigificant. Support for converting Python exceptions to C++ exceptions in Python re-implementations of C++ virtuals not yet implemented. This hasn't been tested - feedback please. sip command passes without error, but I have an error when linking: $OFILES in Makefile contains sipMyModuleMyException.o, while there is no corresponding .cpp file generated. BTW, when I use throw specifier in method signature without corresponding %Exception directive, sip exits with non-zero code, but reports no error message. All tests were done with sip-snapshot-20050626. -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
[PyKDE] Docstrings with SIP
Is there a way to provide docstrings for module, classes and their methods without hacking generated structures? -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] SIP parse error
On Sun, 19 Jun 2005 14:37:48 +0100 Phil Thompson [EMAIL PROTECTED] wrote: On Friday 17 June 2005 9:13 pm, James Emerton wrote: There is a small issue with the parsing code in SIP. I get a parse error whenever a %MethodCode section contains a %, such as a printf() format string. My workaround right now is to use something like this... const char fmt[] = { 37, '0', '4', 'd', 37, '0', '2', 'd', 37, '0', '2', 'd', 0 }; Should be fixed in tonight's snapshot. I see some strange syntax errors with this snapshot for project successfully built with sip-snapshot-20050605. In all cases the error is in %Included file and in one case the error is at line 271 of file having 214 lines. -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] SIP parse error
On Tue, 21 Jun 2005 15:52:15 +0100 (BST) Phil Thompson [EMAIL PROTECTED] wrote: I see some strange syntax errors with this snapshot for project successfully built with sip-snapshot-20050605. In all cases the error is in %Included file and in one case the error is at line 271 of file having 214 lines. Can you send me a test case? Looks like I've found one minimal example: == sip_bug.sip == %Module sip_bug %PostInitialisationCode (void)0; %End %Include MyClass.sip == MyClass.sip == %ModuleHeaderCode class MyClass { public: void method() {}; }; // If you remove next line the error gone %End class MyClass { public: void method(); %MethodCode (void)0; %End }; == $ ./configure_sip_bug.py sip -e -w -c . -b sip_bug.sbf sip_bug.sip sip: MyClass.sip:20: syntax error As you can see MyClass.sip consist of 16 lines only. -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] SIP parse error
On Fri, 17 Jun 2005 13:13:28 -0700 James Emerton [EMAIL PROTECTED] wrote: There is a small issue with the parsing code in SIP. I get a parse error whenever a %MethodCode section contains a %, such as a printf() format string. My workaround right now is to use something like this... const char fmt[] = { 37, '0', '4', 'd', 37, '0', '2', 'd', 37, '0', '2', 'd', 0 }; I have the same issue when using modulo operator. I've defined alternative spelling for it in separate header file as workaround. -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] Handling exceptions in SIP
On Thu, 9 Jun 2005 09:33:22 -0700 James Emerton [EMAIL PROTECTED] wrote: I think there is a need for biderectional conversion of exceptions. I'd like to be able to throw them back into the C++. In fact, a mechanism that could be enable to check the Python error state after calling a Python method from C++ could throw the exception instead of returning to the C++. Could you provide some examples? I see 2 use cases: 1) Your C++ method accepts callback function implemented in Python. SIP translates C++ functions to Python, but it doesn't translate Python callables to C++ ones. You have to call it yourself. There is no even automatic argument translation for it. Why do you think exception should be translated automatically? You can never trust user provided Python code, you can't predict what exceptions it will ever raise, so you have to handle all possible errors. I even can't imaging syntax for backward exception translation. 2) You overwrite virtual method of wrapped class in Python, so that other methods (implemented in C++) use it instead of base. This is more interesting case, but I believe SIP can't handle it too. Please correct me if I'm wrong. So far I don't see any need for automatic backward exception translation, since you have to code mannually Python exception handling anyway. -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
[PyKDE] Static (why?) PyDateTimeAPI and SIP
I use datetime C API in extension module generated with SIP. But SIP break the code into several .cpp files compiled separately and PyDateTimeAPI used by all macros constituting public interface is declared static. The current solution is to define my own functions in main module as workaround: %ModuleHeaderCode PyObject * mxo_PyDateTime_FromDateAndTime(int year, int month, int day, int hour, int minute, int seconds, int usecs); %End %ModuleCode PyObject * mxo_PyDateTime_FromDateAndTime(int year, int month, int day, int hour, int minute, int seconds, int usecs) { return PyDateTime_FromDateAndTime(year, month, day, hour, minute, seconds, usecs); } // and so on for each macro used %End %PostInitialisationCode PyDateTime_IMPORT; %End But I wonder why PyDateTimeAPI is declared static, and is the a better solution? -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] Handling exceptions in SIP
On Mon, 6 Jun 2005 17:54:43 +0100 Phil Thompson [EMAIL PROTECTED] wrote: SIP's exception support was added by a user - I've never used it myself. Suggestions for improvements always welcome. I see the following scenario. User creates exception class and expose it in module namespace (Please correct me if there is a better way): %ModuleCode static PyObject *MyException_object; %End %PostInitialisationCode MyException_object = PyErr_NewException(MyModule.MyException, 0, 0); if (!MyException_object) return; PyDict_SetItemString(sip_mdict, MyException, MyException_object); %End Then he has to define one way mapping for it (assuming MyException has the same interface as std::exception): %MappedType MyException { %ConvertFromTypeCode return PyObject_CallFunction(MyException_object, S, sipCpp-what()); %End %ConvertToTypeCode // We don't need backward convertion, but SIP requires it. *sipIsErr = 1; return 0; %End }; That's all. Now generated code for method with signature void error() throw (MyException); should be equivalent to something like the following: try { sipCpp - Test::error(); } catch (MyException e) { PyObject *MyException_instance = ... // %ConvertFromTypeCode PyObject *MyException_object = PyObject_Type(MyException_instance); PyErr_SetObject(MyException_object, MyException_instance); return NULL; } -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] Handling exceptions in SIP
On Tue, 7 Jun 2005 13:30:29 +0100 (BST) Phil Thompson [EMAIL PROTECTED] wrote: Ok. How about this... %Exception MyException - will be used with an externally defined exception. (Note, you will not be able to specify a base exception, but why would you want to?) %Exception MyException(Base) - will be used to specify a derived exception. SIP will recognise Exception as the standard Python exception, eg. %Exception MyBase(Exception) %Exception MyException(MyBase) Looks a bit tricky, but it suites all possible cases I think. Let it be so. Or maybe an empty base exception should be interpreted as the standard Python exception, eg. %Exception MyBase() ??? It doesn't matter for me. Exactly. Calling PyErr_SetString etc. is quite convenient for extension module authors vs. returning initialized exception instance. So we have... %RaiseCode // Raise a Python exception. sipCpp will be the C++ pointer, // sipException_MyException will be the exception type (unless the // exception was defined externally). PyObject *val = PyObject_CallFunction(sipException_MyException, S, sipCpp-what()); PyErr_SetObject(sipException_MyException, val); %End In most cases it will be even simplier: %RaiseCode PyErr_SetString(sipException_MyException, sipCpp-what()); %End -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
Re: [PyKDE] Wrapped classes without constructor
On Tue, 7 Jun 2005 15:20:40 +0100 (BST) Phil Thompson [EMAIL PROTECTED] wrote: I have several classes which shouldn't be initialized by user. Neither /Abstract/, nor declaring constructor private helps, since in both cases generated class doesn't have destructor, which in my case is mandatory. I use the following code to clear constructor: %PreInitialisationCode sipType_MyClass.td_init = 0; %End Is there a better way I've missed? What version of SIP? $ sip -V 4.2.1 (4.2.1-297) The current snapshot *might* be more helpful as there have been changes in this area. Thanks, after upgrade to recent snapshot wrapped class has destructor with /Abstract/. But the class is added to module namespace. Could the latter be controlled too? -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
[PyKDE] Handling exceptions in SIP
I hope it's correct place to ask general questions about SIP. Am I correct that automatic exception handling in SIP is useless? I see several problems with it. First, the code for method with signature void error() throw (exception); is: try { sipCpp - Test::error(); } catch (exception e) { /* Hope that there is a valid copy ctor. */ exception *sipCpp = new exception(e); sipRaiseClassException(sipClass_exception,sipCpp); return NULL; } The copy of exception is generated and important information is lost (in fact, std::exception used above is never raised itself, but holds what() virtual method redefined in subclasses). Second, the only way to map C++ exception to python object is wrapping exception class, %MappedType doesn't work. But then I see no way to subclass standard Exception class. Am I missing something? -- Denis S. Otkidach http://www.python.ru/ [ru] ___ PyKDE mailing listPyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde