Creating and using wrapped object


    Aug 25 2006 | 9:09 am
    I want to be able to create a new instance of a class as described in
    the newinstance() method in WritingExternals.pdf. I want this instance
    not to be present as an object box but instead being created by another
    external. Once created I want to bind it to a symbol (s->s-thing) and be
    able to send typedmess messages to it.
    Basically I want to do something similar to how a Max wrapper exists for
    Jitter objects, but my external will not have attributes or in other
    ways be jitter-related.
    Apart from the jitter SDK the only example I can find in the SDK is how
    xcoll is created inside coll. I have tried creating the wrapped object
    using newinstance(), but didn't get it to work. I then tried using a
    similar instantiation approach to xcoll. It seems that I am able to
    create the instance, but I'm not able to communicate with it.
    Any cues to how to instantiate the wrapped object, how to create an
    instance of it as part of the wrapper_new method and how to call it
    using typedmess would be appreciated.
    The current version of the code (with heaps of post statements for
    debugging) can be found
    here (jmod.receive is the wrapping object):
    and here (jmod.bindlist is the object being wrapped):
    Thanks a lot,
    Trond
    *

    • Aug 25 2006 | 10:07 am
      I think that the newinstance() strategy only works for classes that
      are compiled together and live in the same binary (as in the coll/
      xcoll case). For 2 distinct objects, as you're proposing, you'll need
      to obex-ify the class you want to instantiate, and use object_new()
      to load it. Even then, if the object hasn't been loaded into Max yet,
      object_new() won't find it, and you'll need to load the class from
      disk. Here's some sample code (untested) which does this. You can use
      freeobject() to free the loaded object later on.
      jb
      t_max_err load_obex_class(t_someobject *x, t_symbol *class_to_load)
      {
      t_class *c = class_findbyname(gensym("box"), class_to_load);
      t_atom a[3];
      // class_to_load could be gensym("jmod.bindlist"), for instance
      if (!c) {
      t_object *p;
      // if not found, attempt to instantiate max object, loading from disk
      if (p=newinstance(class_to_load), 0, NULL)) {
      c = class_findbyname(gensym("box"), class_to_load);
      freeobject(p);
      p = NULL;
      }
      else {
      error("someobject: could not load class %s", class_to_load->s_name);
      return MAX_ERR_GENERIC;
      }
      }
      atom_setsym(&a[0], gensym("arg1"));
      atom_setsym(&a[1], gensym("arg2"));
      atom_setsym(&a[2], gensym("arg3"));
      x->loaded_object = object_new_typed(gensym("box"), class_to_load, 3,
      a);
      return MAX_ERR_NONE;
      }
      Am 25.08.2006 um 11:09 schrieb Trond Lossius:
      > I want to be able to create a new instance of a class as described
      > in the newinstance() method in WritingExternals.pdf. I want this
      > instance not to be present as an object box but instead being
      > created by another external. Once created I want to bind it to a
      > symbol (s->s-thing) and be able to send typedmess messages to it.
    • Aug 25 2006 | 10:18 am
      Oh, I forgot something important. There's a chance that the box entry
      in the loaded object's obex can get a bogus box pointer, which will
      get freed when you call freeobject() on the loaded object. This is
      bad and can cause errors or crashes. You need to do the following
      after creating the object to make everything stable:
      // prototype for function exported from Max
      t_max_err hashtab_store_safe(t_hashtab *x, t_symbol *key, t_object
      *val);
      void *obex;
      if (obex = object_obex_get(x->loaded_object)) {
      hashtab_store_safe(obex, gensym("#B"), (t_object *)NULL);
      }
      jb
      Am 25.08.2006 um 12:07 schrieb Jeremy Bernstein:
      > Here's some sample code (untested) which does this
    • Aug 25 2006 | 10:29 am
      My own code doesn't bear this out, since we use newinstance() to load
      the object from disk, in any case. Well, whatever. The code I sent is
      how I've done what you want to do using obex-bearing objects.
      jb
      Am 25.08.2006 um 12:07 schrieb Jeremy Bernstein:
      > I think that the newinstance() strategy only works for classes that
      > are compiled together and live in the same binary (as in the coll/
      > xcoll case).
    • Aug 25 2006 | 10:39 am
      Thanks a lot, Jeremy!
      I'll keep working on it and see what I manage.
      Trond
      Jeremy Bernstein wrote:
      > My own code doesn't bear this out, since we use newinstance() to load
      > the object from disk, in any case. Well, whatever. The code I sent is
      > how I've done what you want to do using obex-bearing objects.
      >
      > jb
      >
      > Am 25.08.2006 um 12:07 schrieb Jeremy Bernstein:
      >
      >> I think that the newinstance() strategy only works for classes that
      >> are compiled together and live in the same binary (as in the
      >> coll/xcoll case).
    • Mar 31 2009 | 1:44 am
      Resuscitating an old topic here ...
      I'm wanting to do much the same thing, define a class that will NEVER become a full-blown external for instantiation in a Max window, but will be instantiated invisibly as a singleton object bound to a global symbol, for use as a global max listener (it will register for lots of notifications), among other things.
      I'll look at the coll/xcoll source to implement this for Max 4.
      But what is the recommended way of doing this in Max 5? Is there an example available? Even better, has the coll/xcoll source been Max-5-ified for comparisons?
    • Apr 01 2009 | 1:35 am
      Hi John,
      I'm not sure if this is useful info for you, or just rehashing stuff you already know:
      Maybe it helps though...
      best,
      Tim
    • Apr 01 2009 | 3:17 am
      I do believe that is EXACTLY what I am looking for. Many thanks.
    • Apr 03 2009 | 1:10 am
      And indeed it was, I have it working. The Jamoma code linked in your comments was also extremely helpful in getting the separate object files set up correctly. Thanks again Tim.