virtual methods and the t_object offset

Jun 9, 2008 at 11:56pm

virtual methods and the t_object offset

Max relies on the t_object member being located at the very top of your
struct. I’m working in C++ and would like to use an abstract base class for
some of my objects. The problem I run into is that the use of virtual
functions seems to generate additional data at the top of the class. This
therefor breaks the compatibility with Max’ interface. Is it possible to
force a compiler to keep a member like t_object at the beginning of the
object / struct?

Thijs

#38315
Jun 10, 2008 at 12:05am

You could use a functor for this. Something like:
template
class InstanceCallable : public Callable
{
public:
typedef void (O::*Callee)(const char *, Atom *);

InstanceCallable(O &o, Callee c)
: o(o), c(c)
{}

virtual ~InstanceCallable() {}

virtual void call(const char *types, Atom *args) {(o.*c)(types, args);}

protected:
O &o; ///< Instance of a class
Callee c; ///< Instance method to call
};

Then, you would have a static function that called the appropriate
functor instance.

wes

2008/6/9 Thijs Koerselman

:
> Max relies on the t_object member being located at the very top of your
> struct. I’m working in C++ and would like to use an abstract base class for
> some of my objects. The problem I run into is that the use of virtual
> functions seems to generate additional data at the top of the class. This
> therefor breaks the compatibility with Max’ interface. Is it possible to
> force a compiler to keep a member like t_object at the beginning of the
> object / struct?
>
> Thijs
>
>
>

#133358
Jun 10, 2008 at 1:23am

On Tue, Jun 10, 2008 at 1:05 AM, Wesley Smith wrote:

> You could use a functor for this. Something like:
> template
> class InstanceCallable : public Callable
> {
> public:
> typedef void (O::*Callee)(const char *, Atom
> *);
>
> InstanceCallable(O &o, Callee c)
> : o(o), c(c)
> {}
>
> virtual ~InstanceCallable() {}
>
> virtual void call(const char *types, Atom
> *args) {(o.*c)(types, args);}
>
> protected:
> O &o; ///< Instance of a class
> Callee c; ///< Instance method to call
> };
>
>
> Then, you would have a static function that called the appropriate
> functor instance.
>
>
Hi Wes,

I fail to understand both what your code illustrates and how it relates to
my problem. I have a feeling I might not have been very clear in my
explanation, so I’ll try again.

For example consider the following pseudo code:

// Abstract base class that all objects share.

class Base
{
t_jit_object jitob;
virtual void method(); // abstract
}

// Jitter object inheriting from Base

class Object : public Base
{
float member;
void method(); // implementation

}

In such a case Object doesn’t have jitob at the start of its structure, so
if I call methods like jit_class_new() or jit_class_addmethod(), it corrupts
the memory and Max will crash. If the Base class doesn’t have virtual
members, the jitob struct appears at the beginning of the Object class and
everything works fine.

Cheers,
Thijs

#133359
Jun 10, 2008 at 1:38am

Ah,
Now I understand. I don’t think there’s really a way around this.
Once you start using inheritance (and actually in general with C++
although not typically in a single class with no inheritance) C++ is
allowed to put anything at the top of the class object. In other
words, the C++ spec specifically states that the ordering of data in a
class is not guaranteed. When you add virtual methods, things like
the vtable get stuffed in there and change the ordering.

I don’t think there’s a good way around this.

wes

2008/6/9 Thijs Koerselman

:
>
>
> On Tue, Jun 10, 2008 at 1:05 AM, Wesley Smith wrote:
>>
>> You could use a functor for this. Something like:
>> template
>> class InstanceCallable : public Callable
>> {
>> public:
>> typedef void (O::*Callee)(const char *,
>> Atom *);
>>
>> InstanceCallable(O &o, Callee c)
>> : o(o), c(c)
>> {}
>>
>> virtual ~InstanceCallable() {}
>>
>> virtual void call(const char *types, Atom
>> *args) {(o.*c)(types, args);}
>>
>> protected:
>> O &o; ///< Instance of a class
>> Callee c; ///< Instance method to
>> call
>> };
>>
>>
>> Then, you would have a static function that called the appropriate
>> functor instance.
>>
>
> Hi Wes,
>
> I fail to understand both what your code illustrates and how it relates to
> my problem. I have a feeling I might not have been very clear in my
> explanation, so I’ll try again.
>
> For example consider the following pseudo code:
>
> // Abstract base class that all objects share.
>
> class Base
> {
> t_jit_object jitob;
> virtual void method(); // abstract
> }
>
> // Jitter object inheriting from Base
>
> class Object : public Base
> {
> float member;
> void method(); // implementation
>
> }
>
> In such a case Object doesn’t have jitob at the start of its structure, so
> if I call methods like jit_class_new() or jit_class_addmethod(), it corrupts
> the memory and Max will crash. If the Base class doesn’t have virtual
> members, the jitob struct appears at the beginning of the Object class and
> everything works fine.
>
> Cheers,
> Thijs
>
>
>

#133360
Jun 10, 2008 at 5:02am

This is the kind of thing that *should* be possible. Basically yes,
you have no choice, the Jitter object needs to have no vtable (that
doesn’t mean it can’t inherit from another class/struct BTW – I’ve
done that with my C++ Max object code [1]). Not sure if multiple
inheritance would work, but it seems unlikely (or worse, undefined).

If you do need virtuals, there’s surely a pattern (Adapter,
Decorator, Facade perhaps?) that can fudge what you need (OTTOMH).

[1] http://www.mat.ucsb.edu/~wakefield/maxcpp.htm

On Jun 9, 2008, at 6:38 PM, Wesley Smith wrote:

> Ah,
> Now I understand. I don’t think there’s really a way around this.
> Once you start using inheritance (and actually in general with C++
> although not typically in a single class with no inheritance) C++ is
> allowed to put anything at the top of the class object. In other
> words, the C++ spec specifically states that the ordering of data in a
> class is not guaranteed. When you add virtual methods, things like
> the vtable get stuffed in there and change the ordering.
>
> I don’t think there’s a good way around this.
>
> wes
>
>
> 2008/6/9 Thijs Koerselman

:
>>
>>
>> On Tue, Jun 10, 2008 at 1:05 AM, Wesley Smith
>> wrote:
>>>
>>> You could use a functor for this. Something like:
>>> template
>>> class InstanceCallable : public Callable
>>> {
>>> public:
>>> typedef void (O::*Callee)(const
>>> char *,
>>> Atom *);
>>>
>>> InstanceCallable(O &o, Callee c)
>>> : o(o), c(c)
>>> {}
>>>
>>> virtual ~InstanceCallable() {}
>>>
>>> virtual void call(const char
>>> *types, Atom
>>> *args) {(o.*c)(types, args);}
>>>
>>> protected:
>>> O &o; ///< Instance of a
>>> class
>>> Callee c; ///< Instance
>>> method to
>>> call
>>> };
>>>
>>>
>>> Then, you would have a static function that called the appropriate
>>> functor instance.
>>>
>>
>> Hi Wes,
>>
>> I fail to understand both what your code illustrates and how it
>> relates to
>> my problem. I have a feeling I might not have been very clear in my
>> explanation, so I’ll try again.
>>
>> For example consider the following pseudo code:
>>
>> // Abstract base class that all objects share.
>>
>> class Base
>> {
>> t_jit_object jitob;
>> virtual void method(); // abstract
>> }
>>
>> // Jitter object inheriting from Base
>>
>> class Object : public Base
>> {
>> float member;
>> void method(); // implementation
>>
>> }
>>
>> In such a case Object doesn’t have jitob at the start of its
>> structure, so
>> if I call methods like jit_class_new() or jit_class_addmethod(),
>> it corrupts
>> the memory and Max will crash. If the Base class doesn’t have
>> virtual
>> members, the jitob struct appears at the beginning of the Object
>> class and
>> everything works fine.
>>
>> Cheers,
>> Thijs
>>
>>
>>

Be seeing you

grrr waaa
http://www.grahamwakefield.net

#133361
Jun 10, 2008 at 10:22am

Thomas Grill’s flex environment manages. Have you tried taking a look at that?

– P.

#133362
Jun 10, 2008 at 11:42am

On Tue, Jun 10, 2008 at 11:22 AM, Peter Castine

wrote:

>
> Thomas Grill’s flex environment manages. Have you tried taking a look at
> that?
>
>

Thanks guys! I should have a look at how flext approaches this, but I don’t
want to use the framework myself. I currently use your template approach,
Graham, which I like a lot. I’ve used single inheritance without virtual
functions successfully with it. I think I’ll go spend some time in the sun
with my GOF book to figure out how to get what I want using the patterns you
mentioned.

Cheers,
Thijs

#133363

You must be logged in to reply to this topic.