wxLua 2.8.10 introduced multiple inheritance in the C++ bindings which wxWidgets uses for the wxComboBox, wxChoice, and wxBitmapComboBox classes. However, I was not aware that C++ compilers shift the vtable of the second and higher base classes and therefore if you directly cast a void* pointer to an object to its second or higher base class you will segfault when you try to call one of its functions. I have finally come across a solution that does work for GCC and MSVC, but it is compiler implementation dependent. The only other compiler that I think we may care about is the Intel one, which I cannot test. The bottom line is that the code will probably not even compile or immediately segfault when called if GCC or MSVC change their code generation (unlikely), which is fine since we can fix it then, for the foreseeable future this will work even though it may upset C++ purists.
Below is a comment in wxlstate.cpp describing in more detail the problem and the solution that I have just committed to CVS. // Note about multiple inheritance in wxLua : // See wxLuaBindClass::baseclass_vtable_offsets // // class A { int x; }; class B { int y; }; class AB : public A, public B { int z; }; // AB ab; void *v_ab_a = (A*)&ab; void *v_ab_b = (B*)&ab; // long int dummy = 0; // long int AB_diff = ((long int)(B*)(AB*)&dummy) - ((long int)(A*)(AB*)&dummy); // wxPrintf(wxT("AB*=%p, A*=%p, B*=%p, B*-A*=%d\n"), &ab, v_ab_a, v_ab_b, AB_diff); // prints: "AB*=0x614dfc, A*=0x614dfc, B*=0x614e00, B*-A*=4" // // In order to call B's functions from a void* pointer to an AB object : // 1) Ideally, we cast to an AB object and the compiler will appropriately lookup // and handle calls to B's functions. // 2) Cast to an AB object then to a B object where the compiler has already // shifted the pointer and calls to B's functions are made directly. // 3) Explicitly shift the void* pointer to the AB object to where the vtable for // B is. We now have an object that only knows about B and what B was derived from. // I'm sure this is frowned upon by C++ enthusiasts. // // Ways doing 1 and 2 in wxLua with C++ constraints, wxLua does #3 above. // // 1) wxLua would duplicate all the the binding functions for second // and higher base classes and therefore each binding function will cast the // void* we get from Lua to exactly the object type that it is. This is best, // but it adds bloat. // 2) Come up with a clever way using overloaded functions, templates, // or some sort of variant class to convert the void* pointer from Lua to // type of object that it really is (we know by the wxLuaType integer) // and then the binding function will cast it whatever base class it may be. // The problem is that we really need to overload this casting function by // return type, the function takes void* and returns ClassXYZ*, but this // is not allowed in C++. // 3) Store an array of the offsets in each classes' wxLuaBindClass struct // to the second or higher base classes and automatically add this offset in // wxluaT_getuserdatatype(). The offsets are calculated at compile time // using the AB_diff method above. // // Various ways to cast a void* pointer to the second base class : // void* v_ab = &ab; // compilier doesn't know what v_ab is anymore // AB* ab = (AB*)v_ab; // ok since we cast right back to original type // A* a = (A*)v_ab; // ok in GCC & MSVC since we are casting to 1st base class // B* b = (B*)v_ab; // segfault! since B*'s vtable is +4 bytes as shown above // B* b1 = (B*)(AB*)v_ab; // ok since compiler converts to AB* and knows that B* is shifted // B* b2 = (B*)((long int)v_ab + AB_diff); // ok since we've shifted to B Regards, John ------------------------------------------------------------------------------ Come build with us! The BlackBerry® Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9-12, 2009. Register now! http://p.sf.net/sfu/devconf _______________________________________________ wxlua-users mailing list wxlua-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/wxlua-users