<div dir="ltr">Hi,<br><br>I experience a new virtual class address issue using sip 4.19.21-4.19.25.<br>I have a rather complex C++ inheritance tree, using virtual inheritance and diamond inheritance, looking like this:<br><br>    A     B<br>    \\   //<br>     \\ //<br> D     C<br>  \  // \\<br>   \//   \\<br>    E     F<br>    \\   //<br>     \\ //<br>       G<br><br>(double lines mean virtual inheritance)<br><br>In recent Sip bindings the addresses of the different parts of a G object appear to be wrong, thus objects are unusable and cause crashes.<br><br>Here is a simple C++ implementation code:<br><br>// header declarations:<br><br>#include <iostream> // not used here but simplifies the sip MethodCodes later<br><br>class A<br>{<br>public:<br>  A();<br>  virtual ~A();<br>  int a;<br>};<br><br><br>class B<br>{<br>public:<br>  B();<br>  virtual ~B();<br>  int b;<br>};<br><br>class C : public virtual A, public virtual B<br>{<br>public:<br>  C(): c(3) {}<br>  virtual ~C() {}<br><br>  int c;<br>};<br><br>class D<br>{<br>public:<br>  D();<br>  virtual ~D();<br>  int d;<br>};<br><br>class E: public D, public virtual C<br>{<br>public:<br>  E();<br>  virtual ~E();<br>};<br><br>class F : public virtual C<br>{<br>public:<br>  F();<br>  virtual ~F();<br>};<br><br>class G : public virtual E, public virtual F<br>{<br>public:<br>  G();<br>  virtual ~G();<br>  int g;<br>};<br><br><br>// C++ implementation<br><br>A::A(): a( 1 ) {}<br>A::~A() {}<br><br>B::B(): b( 2 ) {}<br>B::~B() {}<br><br>C::C() : A(), B(), c( 3 ) {}<br>C::~C() {}<br><br>D::D() : d( 4 ){}<br>D::~D() {}<br><br>E::E() : D(), C() {}<br>E::~E() {}<br><br>F::F() : C() {}<br>F::~F() {}<br><br>G::G() : E(), F(), g( 7 ) {}<br>G::~G() {}<br><br><br>// SIP bindings file<br><br><br>class A<br>{<br>%TypeHeaderCode<br>#include "test.h"<br>%End<br><br>public:<br>  A();<br>  virtual ~A();<br>  void __a__();<br>%MethodCode<br>  std::cout << "A: " << sipCpp << std::endl;<br>%End<br><br>  int a;<br>};<br><br><br>class B<br>{<br>%TypeHeaderCode<br>#include "test.h"<br>%End<br><br>public:<br>  B();<br>  virtual ~B();<br>  void __b__();<br>%MethodCode<br>  std::cout << "B: " << sipCpp << std::endl;<br>%End<br><br>  int b;<br>};<br><br><br>class C : A, B<br>{<br>%TypeHeaderCode<br>#include "test.h"<br>%End<br><br>public:<br>  C();<br>  virtual ~C();<br>  void __c__();<br>%MethodCode<br>  std::cout << "C: " << sipCpp << std::endl;<br>%End<br><br>  int c;<br>};<br><br><br>class D<br>{<br>%TypeHeaderCode<br>#include "test.h"<br>%End<br><br>public:<br>  D();<br>  virtual ~D();<br>  void __d__();<br>%MethodCode<br>  std::cout << "D: " << sipCpp << std::endl;<br>%End<br>  int d;<br>};<br><br>class E : D, C<br>{<br>%TypeHeaderCode<br>#include "test.h"<br>%End<br><br>public:<br>  E();<br>  virtual ~E();<br>  void __e__();<br>%MethodCode<br>  std::cout << "E: " << sipCpp << std::endl;<br>%End<br>};<br><br><br>class F : C<br>{<br>%TypeHeaderCode<br>#include "test.h"<br>%End<br><br>public:<br>  F();<br>  virtual ~F();<br>  void __f__();<br>%MethodCode<br>  std::cout << "F: " << sipCpp << std::endl;<br>%End<br>};<br><br><br>class G : E, F<br>{<br>%TypeHeaderCode<br>#include "test.h"<br>%End<br><br>public:<br>  G();<br>  virtual ~G();<br>  void __g__();<br>%MethodCode<br>  std::cout << "G: " << sipCpp << std::endl;<br>%End<br><br>  int g;<br>};<br><br>// end code<br><br>(the source files are also attached to the message)<br><br>Thus each class X in python has a __X__() method which prints its C++ address, and a number of classes have an int data to check the value.<br><br>Now if we run this python test:<br><br>import test<br><br>def print_all(x, methods='abcdefg'):<br>    for att in methods:<br>        m = getattr(x, '__%s__' % att, None)<br>        if m:<br>            m()<br>    print()<br>    for att in methods:<br>        m = getattr(x, '%s' % att, None)<br>        if m:<br>            print('%s:' % att, m)<br><br>g = test.G()<br><br>print_all(g)<br><br><br>This test outputs, using sip 4.19.21 to 4.19.25:<br><br>A: 0x36fd720<br>B: 0x36fd720<br>C: 0x36fd720<br>D: 0x36fd738<br>E: 0x36fd738<br>F: 0x36fd720<br>G: 0x36fd720<br><br>a: 7<br>b: 7<br>c: 7<br>d: 4<br>g: 7<br><br>As you see object parts A, B, C, F and G all have the same address in the bindings, whereas they obviously do not have the same address in C++ (A, B and C are not related). Moreover as the offsets of virtual tables and data in the object are wrong, the int values are wrong for most of them (a, b and c all seem to contain 7 whereas they should contain 1, 2 and 3).<br><br>Using sip 4.19.15, the output of the same code was:<br><br>A: 0x1f72ed8<br>B: 0x1f72ee8<br>C: 0x1f72ec8<br>D: 0x1f72eb8<br>E: 0x1f72eb8<br>F: 0x1f72ea0<br>G: 0x1f72ea0<br><br>a: 1<br>b: 2<br>c: 3<br>d: 4<br>g: 7<br><br>which is totally correct.<br><br>In the sip code, if I remove the inheritance from C in F (just in the sip code, not changing anything in the C++ part), then things become right for a G object (using sip 4.19.25 again):<br><br>A: 0x31b5798<br>B: 0x31b57a8<br>C: 0x31b5788<br>D: 0x31b5778<br>E: 0x31b5778<br>F: 0x31b5760<br>G: 0x31b5760<br><br>a: 1<br>b: 2<br>c: 3<br>d: 4<br>g: 7<br><br>But obviously an instance of F will now be missing its A, B and C parts.<br><br>After trying all this I remember that we have had possibly similar problems in the first releases of sip 4.19:<br><a href="https://www.riverbankcomputing.com/pipermail/pyqt/2019-February/041313.html">https://www.riverbankcomputing.com/pipermail/pyqt/2019-February/041313.html</a><br>I haven't tested with the same example yet, so I'm not sure it's the same problem which has re-appeared.<br><br>Thanks for your help,<br>Denis<br><br><br></div>