[PyQt] sip: extend exception support
Mathias.Born at gmx.de
Mathias.Born at gmx.de
Sun Aug 26 13:30:32 BST 2012
On 26.08.2012, 16:46:24 Phil Thompson wrote:
> On Wed, 15 Aug 2012 15:54:11 +0200, Mathias.Born at 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::optional<int> sipVH_ltse_app_0(sip_gilstate_t
> sipGILState,PyObject
>> *sipMethod,const std::string& a0)
>> {
>> boost::optional<int> 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
More information about the PyQt
mailing list