[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: [tolua++] support multiple inehritance
- From: Christian Vogler <Christian.Vogler@...>
- Date: Fri, 30 Sep 2005 19:59:19 -0400
On Friday 30 September 2005 06:23 pm, Mildred wrote:
> Is it possible to have multiple inehritance with tolua++ w/o using
> syntax like:
> myobject.__parent__:mymethod()
> ?
I have not looked at tolua++ in a long time, but things used to be much more
complicated than that. You have to be very careful with casting in the
presence of multiple inheritance. Consider this layout:
class A {
};
class B {
};
class Derived : public A, public B {
};
Most compilers will layout Derived in memory such that the part from class A
comes before class B.
If you then instantiate a Derived object and reference it through a pointer to
the base class B
Derived *object = new Derived();
B *base_obj = object;
"object" points to the beginning of the Derived class as a whole, but
"base_obj" actually points to the beginning of B in the Derived class layout,
not the beginning of the Derived class as a whole. This works, because the
compiler is aware of the involved types and can correct the pointers with the
appropriate offsets when you cast.
The problem is that tolua uses void * pointers, which loses all type
information. Tolua does a direct cast from void * to the object's actual type
when necessary. If you have a tolua binding that takes a B * as an argument,
things go haywire in a hurry:
local object = Derived:new()
do_something(object)
where the signature is
void do_something(B *object);
When the object is instantiated in Lua, you have a void * pointer to the
beginning of Derived. In the tolua binding for the do_something function,
this pointer is retrieved and directly cast from void * to B *.
*Oops.* Now the pointer of type B * actually points to the beginning of the
object, instead of the middle where the B class actually is laid out.
What needs to happen is this cast sequence:
void * -> Derived * -> B *,
so for safe multiple inheritance in tolua, any pointer must first be cast to
the object's original type, and only then it is safe to cast to the base
class type.
One way to solve this problem is to generate a bunch of cast functions, like
this:
/* Function to cast properly from derived types to base types, */
/* even in the presence of multiple inheritance. */
#ifdef __cplusplus
template<class Derived, class Base>
void *tolua_do_cast(void *p)
{
Derived *d = static_cast<Derived *>(p);
return static_cast<Base *>(d);
}
#endif
Then you need to populate a table indexed by the derived/base class metatable
pairs, and a pointer to the appropriate cast function as the values. Every
time tolua casts a userdata object, it needs to look up the appropriate
function, based on the object's actual type (which can be determined only at
run time) and the target type, then call it to get the correct pointer. It
sure is messy, and also entails a slight performance hit. :-(
Anyway, I made such a modification to tolua 4, just so that it would not crash
on data types that had hidden mix-in classes. If anyone is interested and
thinks that they might be useful for tolua++ and lua 5, let me know, and I
can make the changes available.
Regards
- Christian
--
Christian Vogler, Ph.D.
Research Scientist, Gallaudet Research Institute
http://gri.gallaudet.edu/~cvogler/