testobex example in pattrsdk.pdf

    Jul 11 2006 | 9:47 pm
    I tried compiling the testobex external in the pattrsdk.pdf and found a few errors. I corrected the errors but still the example does not work correctly.
    firstly, void *class_testobex was declared but then was used as testobex_class twice. so i changed it to class_testobex.
    secondly, the attribute 'operand' was registered but then 'data' was used in place of 'operand' . I changed all instances of 'data' to 'operand' and it compiled fine.
    When i set up a test in max however, the output value was always 0. I did put a value for operand in the object 'command line' ie
    @operand 34
    any idea on how to correct this?

    • Jul 12 2006 | 7:09 pm
      I decided to post the source. It is the same as in pattrsdk.pdf with the changes i mentioned.
      I have it working when i manually set operand to the value (which i commented out here), so maybe i am confused by the point of
      //handle attribute arguments (e.g. @operand 0.5)
      attr_args_process(x, ac, av);
      does it not set the values of the attributes to the variable you create and register with class_addattr(c, attr); ?
      #include "ext.h"
      #include "ext_obex.h"
      typedef struct _testobex
      { t_object ob;
      void *obex;
      float operand;
      void *out;
      } t_testobex;
      void *class_testobex;
      void *testobex_new(t_symbol *s, long ac, t_atom *av);
      void testobex_free(t_testobex *x);
      void testobex_int(t_testobex *x, long d);
      void testobex_float(t_testobex *x, double f);
      void main(void)
      { t_class *c;
      t_object *attr;
      long attrflags = 0;
      // define the class – A_GIMME required for attributes
      c = class_new("testobex", (method)testobex_new, (method)testobex_free, sizeof(t_testobex), (method)0L, A_GIMME, 0);
      // register the obex object's offset
      class_obexoffset_set(c, calcoffset(t_testobex, obex));
      // create and register an attribute (attr_offset)
      attr = attr_offset_new("operand", _sym_float32, attrflags, (method)0L, (method)0L, calcoffset(t_testobex, operand));
      class_addattr(c, attr);
      // create and register some methods
      class_addmethod(c, (method)testobex_int, "int", A_LONG, 0);
      class_addmethod(c, (method)testobex_float, "float", A_FLOAT, 0);
      // add dumpout and quickref methods
      class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0);
      class_addmethod(c, (method)object_obex_quickref, "quickref", A_CANT, 0);
      // register the class as an instantiable box
      class_register(CLASS_BOX, c);
      // set the global class variable
      class_testobex = c;
      void *testobex_new(t_symbol *s, long ac, t_atom *av)
      { t_testobex *x = NULL;
      // allocate a new object
      if (x = (t_testobex *)object_alloc(class_testobex))
      { // important: initialize class members before processing
      // attribute args. otherwise, you might replace data.
      x->operand = 0;
      //handle attribute arguments (e.g. @operand 0.5)
      attr_args_process(x, ac, av);
      // if (ac > 1) x->operand = atom_getlong(av+1);
      // create a dumpout outlet, used by attributes
      object_obex_store(x, _sym_dumpout, outlet_new(x, NULL));
      // create another outlet
      x->out = outlet_new(x, NULL);
      return x;
      void testobex_free(t_testobex *x)
      { ; // nix
      void testobex_int(t_testobex *x, long d)
      { // int in, int out
      outlet_int(x->out, (long)((float)d * x->operand));
      void testobex_float(t_testobex *x, double f)
      // float in, float out
      outlet_float(x->out, f * x->operand);