Struct and constructor ?

Oct 3, 2012 at 2:29pm

Struct and constructor ?

Hello,

this is a speculative question in C++ context ; is there any way to call the constructor of the object’s struct at instantiation (object_alloc do not do it).

typedef struct _flop {
   t_object ob;
   void *outlet;
   _flop( ) { post("???"); }
} t_flop;

void *flop_new(t_symbol *s, long argc, t_atom *argv)
{
   t_flop *x = NULL;

   if (x = (t_flop *)object_alloc(flop_class)) {
      x->outlet = bangout((t_object *)x);
   }

   return x;
}
#64598
Oct 3, 2012 at 3:00pm

That’s just a stupid exercise to learn auto_ptr syntax. I would like to implement something like that :

typedef struct _flop {
   t_object ob;
   void *outlet;
   auto_ptr ptr;
   _flop( ) : ptr(new Oizo) { post("???"); }
} t_flop;

but it doesn’t work ; and i don’t even know if it is possible ;-)

#233044
Oct 4, 2012 at 8:02am

Salut Nicolas

That’s interesting.

In principle, I don’t think you can declare a C++ constructor inside a C struct – you need to declare a C++ class and instantiate it C++ style in order to call the constructor, and this is not what object_alloc() does.

In order to have a C++ object inside a Max object, I’d say the only way to go is the one demonstrated in the collect example…

… but I’d love someone more knowledgeable than me to chime in!

aa

#233045
Oct 4, 2012 at 9:56am

Hi,

As the file is builded by C++ complier the struct is a C++ struct ; so it is can be used exactly as a Class with everything public by default ; in my exemple if you do something like :

void f( )
{
   t_flop temp;
}

the constructor is called as it should. But you are right, here the instantiation is done by object_alloc who is a C function so i’m pretty sure that it is a very dangerous code… and therefore a good exercise ;-)

It seems to work with a init( ) function that i call later ; but it does not allow me to instantiate the auto_ptr properly. Of course all that stuff is just a test and i do not think it should be used in production code but the idea to encapsulate the auto release with the allocation is smart enough to explore that.

if (x = (t_flop *)object_alloc(flop_class)) {
   (*x).init( );
   x->outlet = bangout((t_object *)x);
}

Anyway thanks for reply.

#233046
Oct 4, 2012 at 12:00pm

Hi,

what I usually do when developing externals is, to declare an object class like this:

// Object Class
  class ObjectClass {
  public:
    t_object object;
    // Own stuff
  };

Then, in my create function I do this:

void * x;

  x = object_alloc ( classPtr );
  new ( x ) ObjectClass ( );
  return ( ObjectClass * ) x;

Of course, you need to #include in order to access the new function.

Hope this helps,
Ádám

#233047
Oct 4, 2012 at 2:31pm

Hello,

Thanks Ádám !

That seems to work now ; anybody see something unsafe there ?

typedef struct _flop {
    t_object ob;
    void *outlet;
    _flop( ) { post("Constructor"); }
    ~_flop( ) { post("Destructor"); }
} t_flop;

void *flop_new(t_symbol *s, long argc, t_atom *argv)
{
    t_flop *x = NULL;

    if (x = (t_flop *)object_alloc(flop_class)) {
        new(x)t_flop( );
        x->outlet = bangout((t_object *)x);
    }

    return x;
}

void flop_free(t_flop *x)
{
    x->~t_flop( );
}
#233048
Oct 4, 2012 at 2:59pm

And with that (Oizo is the name of another class) the smart pointer seems to do the job… a little bit over complex that necessary ? No, not at all ;-)

typedef struct _flop {
    t_object ob;
    void *outlet;
    auto_ptr ptr;
    _flop( ) : ptr(new Oizo) { }
    ~_flop( ) { }
} t_flop;
#233049
Oct 4, 2012 at 3:10pm

Hi,

actually, this is what I do all the time. All my externals are actually developed in C++ and I never had any problem by using this initialization style.
There’s one little trick that you need to consider, though. If your object is initialized with invalid arguments and you want the ‘gray box’ effect, you have to set a flag in the constructor that later you can read from your new method. An example from my object [sadam.envelopeGenerator]:

void * create ( t_symbol * sym, const long argc, t_atom * argv ) {
    void * x;
    ObjectClass * envelopeGenerator;

    x = object_alloc ( classPtr );
    new ( x ) ObjectClass ( sym, argc, argv );
    envelopeGenerator = ( ObjectClass * ) x;
    if ( envelopeGenerator && ! envelopeGenerator->isValid ) {
      delete envelopeGenerator;
      envelopeGenerator = NULL;
    }
    return envelopeGenerator;

  }
#233050
Oct 4, 2012 at 5:21pm

Hello,

Thanks again ; even if i’m not sure i will use this approach later ; that’s three days that i try to find how to do it with an “auto_ptr” and so i’m very happy today : i solved the problem ! Hip hip hooray !

#233051

You must be logged in to reply to this topic.