Linking attributes to a struct within an object
Hi there - I've been trying to add attributes to my custom external, but find the documentation rather sparse.
My object's struct looks rather like this:
typedef struct _myObj {
t_pxobject x_obj;
otherStruct *e;
} t_myObj;
with otherStruct defined as (shortened here):typedef struct otherStruct
{
float x,y,offsetx,offsety,angle;
} otherStruct;
I have a whole list of strings:const char* paramNames[5] = {"x","y", "offsetx","offsety","angle"};
To set up the attributes I do the following
for (i=0;i
int offset = i*sizeof(t_atom_float);
t_object *attr = attr_offset_new ( paramNames[i], _sym_float32, 0, (method)0L, (method)0L, offset);
if (attr == NULL) {
object_error((t_object *)x, "Couldn't create new attr at offset %ld",offset);
} else {
t_max_err err = object_addattr(x->e, attr);
if (err != MAX_ERR_NONE) {
object_error((t_object *)x, "object_addattr failed with error code %ld",err);
}
}
}
But this crashes in 'object_addattr'. What am I doing wrong? Can the first argument in 'object_addattr' just be any old struct, or does it have to be a t_object*? (The fact it's a void* seems to imply that it's OK, but who knows?)
thanks! i'll look into these
Hi,
You can have a look at for OBJECT_ATTR.
Cheers
Yes, you are right ! It works but I don't know where is my attribute... In fact, it seems that m_order isn't the variable of my attribute. I used to use object_attr_get so I didn't realize the problem. OBJ_ATTR_LONG (&m_order) isn't the solution, I'll have to investigate...
Thanks for this feedback !
I tried OBJ_ATTR_FLOAT using pointers directly to my struct, but it didn't work. I've given up and refactored the object so that it's not using a struct within a struct any more. Then I can just use CLASS_ATTR_FLOAT (albeit with 30 lines more code).
I think I can confirm this. In my former version of the code (posted in the initial message), in which I used obj_addattr (which is what the OBJ_ATTR macros use) to point to an arbitrary struct (NOT an 'object' struct, i.e. without the t_pxobject as the first member), there seemed to be no way to directly change the value of it by simply writing to the point with which it was initialized.
When I then refactored the code so that all the arbitrary struct members became part of my Max object struct, I could change the attribute value by directly writing to that memory space.
So, in short, it seems neither CLASS_ATTR nor OBJ_ATTR macros work with any struct that doesn't have t_pxobject as a first member....?
Sorry, I saw this thread late, but - yes - to answer mnorris question please refer to my thread that Nicolas kindly dug out of the archives. The only thing I would like to add is that in this specific case I use the _sym_pointer qualifier as it is more correct for the type of use. Of course custom getter and setter are mandatory...
Best
- Luigi
Hi there!
I am a (very) newbie in MaxMSP and I already have to create my own external. My problem is very close to yours (I guess): I want to read 5 text files and get access to each one of them in my object. To do this I have created a struct to fill in the data. Each time a message "read" incomes I create a new structure that I fill with the data from the text file, my problem is how to get access to those 5 structures in the rest of my program?
Should I add some attributes to my object (but add then 5 struct attributes?)
the structures:
typedef struct _recognition {
t_object p_ob;
void *p_outlet;
} t_recognition;
typedef struct _model {
char id;
double A[NBSTATE][NBSTATE];
double cov[NBSTATE*NBFEAT][NBFEAT];
double mu[NBSTATE][NBFEAT];
} t_model;
In the main
c = class_new("recognition", (method)recognition_new, (method)NULL, sizeof(t_recognition), 0L, A_DEFLONG, 0);
class_addmethod(c, (method)myobject_read, "read", A_DEFSYM, 0);
the functions:
void myobject_read(t_object *x, t_symbol *s)
{
defer(x, (method)myobject_doread, s, 0, NULL);
}
void myobject_doread(t_object *x, t_symbol *s)
{
// ..... find the filename etc
myobject_openfile(x, filename, path);
}
t_model *myobject_openfile(t_object *x, char *filename, short path)
{
t_filehandle fh;
char *buffer;
t_ptr_size size;
int count=0;
t_model *mod = (t_model *)malloc(sizeof(t_model));
if (path_opensysfile(filename, path, &fh, READ_PERM)) {
object_error(x, "error opening %s", filename);
return mod;
}
mod->id=filename[6];
// allocate memory block that is the size of the file
sysfile_geteof(fh, &size);
buffer = sysmem_newptr(size);
// read in the file
sysfile_read(fh, &size, buffer);
sysfile_close(fh);
// fill the structure mod
sysmem_freeptr(buffer); // must free allocated memory
return mod;
}
So each time there is a "read" message, I create and fill a new structure t_model *mod and send back a pointer to this structure but where can I access to it? And how to be sure I create a new structure for each read and not writing over?
Thank you to answer me so quickly!
I need indeed to access my five t_model in other methods of my external. I think you are right saying I need an array of pointers. But how I can instantiate them without a malloc? I have found the function system_newptr but it looks to work only with pointers of type char and I need pointers of type t_model.
I have tried this:
in my object structure:
t_model *ptr_model[5];
in the method to instantiate the object (my object_new)
for(int i=0; iptr_model[i]=sysmem_newptr(sizeof(t_model));
}
and I get a warning "Incompatible pointer type assigning to 't_model *' from 't_ptr'"
Is there any other function to do so?
I am sure that my problem is about knowing generic techniques for Max/MSP objects and I have already make smaller objects from my own and read the examples in MaxSDK in order to understand the basics but it looks not to be enough.
Actually it looks to work even with the warning. Thank you a lot!