[PyQt] SIP and virtual functions

Phil Thompson phil at riverbankcomputing.com
Tue Nov 23 14:42:59 GMT 2010


On Tue, 23 Nov 2010 15:22:39 +0100, Jens Thoms Toerring <jt at toerring.de>
wrote:
> Hi,
> 
> I've got some problem with sip when using classes that have
> virtual methods. The classes look somewhat like this (this is,
> of course, just an example, cut down to the absolute essen-
> tials and not my real code):
> 
> -------- Foo.hpp ------------------------------
> #if ! defined FOO_HPP_
> #define FOO_HPP_
> 
> class A {
>     friend class B;
>   private:
>     A( double & x );
> };
> 
> class B {
>   public:
>     virtual A a( );
>   private:
>     double m_x;
> };
> 
> class C : public B {
> };
> 
> #endif
> -------- Foo.cpp ------------------------------
> #include "Foo.hpp"
> 
> A::A( double & x ) { x = 3; }
> 
> A B::a( ) { return A( m_x ); }
> ----------------------------------------------
> 
> Now I have a Foo.sip file
> 
> -------- Foo.sip ------------------------------
> %Module PyFoo 0
> 
> class A  /NoDefaultCtors/
> {
> %TypeHeaderCode
> #include "Foo.hpp"
> %End
> };
> 
> class B
> {
> %TypeHeaderCode
> #include "Foo.hpp"
> %End
>   public:
>     virtual A a( );
> };
> 
> class C : B
> {
> %TypeHeaderCode
> #include "Foo.hpp"
> %End
> };
> ---------------------------------------------
> 
> This sip file results in the creation of the following function
> in the sipPyFoocmodule.cpp file
> 
> A sipVH_PyFoo_0(sip_gilstate_t sipGILState,PyObject *sipMethod)
> {
>     A sipRes;
>     PyObject *resObj = sipCallMethod(0,sipMethod,"");
> 
>     if (!resObj ||
>     sipParseResult(0,sipMethod,resObj,"H5",sipType_A,&sipRes) < 0)
>         PyErr_Print();
> 
>     Py_XDECREF(resObj);
>     Py_DECREF(sipMethod);
> 
>     SIP_RELEASE_GIL(sipGILState)
> 
>     return sipRes;
> }
> 
> and there's a problem with the first line of this function: the
> constructor of class A is private - and that's by design since
> A is only to be instantiated via class B. The function a() in B
> for creating an instance of A must be virtual since class C (or
> some other derived class) must be able to have it's own version
> of the a() function to do some extra checks before explicitely
> invoking the base class B::a() function - and the 'virtual'
> qualifications seems to be at the heart of the problem, with-
> out it the above function doesn't get generated.
> 
> I have played around with all kinds of annotations but found no
> way to avoid the creation of this kind of function (or it's attempt
> to invoke a private constructor). In my real code in somewhat more
> complex situations also non-existing constructors are attemted to
> be used (e.g. constructors with a single int argument which don't
> exist at all).
> 
> Has anyone an idea what I'm doing wrong and/or how to resolve
> this issue?

Not every C++ class can be wrapped. SIP often has to create temporary
instances which obviously requires support from the underlying C++.

Phil


More information about the PyQt mailing list