Linking attributes to a struct within an object

Aug 30, 2013 at 10:30pm

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<kNumParams;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?)

#263794
Aug 30, 2013 at 11:11pm

Hi,

1. I did an exercise that might help you ( https://github.com/nicolasdanet/Flop/blob/master/Sources/Flop/flapOffset.c ).
2. Concerning class vs object attributes you should read that : ( http://cycling74.com/forums/topic/deleting-attributes/ ).
3. AFAIK the first argument of object_addattr must be a max object pointer ; but i’m not as expert as Luigi Castelli concerning attributes.

4. To post a multi-line segment of code in the forum use “pre” tag instead of “code”.

#263795
Aug 30, 2013 at 11:41pm

thanks! i’ll look into these

#263796
Aug 30, 2013 at 11:51pm

The trick in my example is to allocate the attribute structure right after the class structure by oversizing the memory allocated in the class_new method. That seems to work well for class attributes. I never used instance attributes so i have no idea how to deal with.

#263797
Aug 31, 2013 at 7:48am

Hi,
You can have a look at for OBJECT_ATTR.

Cheers

#263824
Aug 31, 2013 at 7:49am
#263825
Aug 31, 2013 at 8:16am

Hi Pierre,

Here ( https://github.com/CICM/HoaLibrary/blob/master/Max6/MaxAmbisonic.cpp#L35 ) it seems the last argument passed to OBJ_ATTR_LONG (m_order) is a type long ; according to the documentation, a pointer is required. Am i wrong ?

#263826
Aug 31, 2013 at 9:40am

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 !

#263836
Aug 31, 2013 at 10:12am

OBJ_ATTR_LONG (&m_order) doesn’t work? My first attempt would have been something like that! Anyway i’ll investigate also ;-)

#263840
Aug 31, 2013 at 1:04pm

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).

#263853
Sep 1, 2013 at 12:03am

Hi,

It seems that the pointer required in the OBJ_ATTR macro is used only for initializing the value but the storage and the memory allocated for that value is managed under-the-hood. To change that value you need to call the getter and the setter.

Anybody to confirm or to refute ?

#263880
Sep 1, 2013 at 3:14am

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….?

#263885
Sep 1, 2013 at 4:04am

1. Requirement for those macros is more generally a t_object instead of a t_pxobject ; but in no way they can be used on a raw structure.
2. OBJ_ATTR and CLASS_ATTR seems not manage the memory visibility in the same way ; and the similarity of their names is misleading.
3. I can not find any situation where define attributes in a custom structure (as i done for fun in my “flapOffset” example) is a good idea.

#263887
Sep 1, 2013 at 7:37am

Hi,

I have investigated a bit more and it seems that the documentation about OBJ_ATTR_LONG is false!

The long is passed by value ( https://github.com/nicolasdanet/Flop/blob/master/Sources/Flop/flopObject.c#L98 )
whereas in other case (such as OBJ_ATTR_DOUBLE_ARRAY) it is by pointer???

I’ll explore deeper and collect examples in my “flopObject.c” external.

@Pierre: Your code was good!

Ciao.

#263898
Sep 2, 2013 at 11:16pm

Hi again,

Just found this ( http://cycling74.com/forums/topic/setting-and-getting-attributes/ ) that seems to give a clue to resolve the Mnorris’s first question. I’ll make a test.

#264076
Sep 2, 2013 at 11:39pm

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

#264081
Sep 3, 2013 at 7:32am
#264103
Nov 12, 2013 at 3:40am

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?

#270937
Nov 12, 2013 at 6:15am

Hi,

1. You don’t have to use attributes except if you need your data to be accessed from outside your external (“pattr” compatibility, save data in the patcher…).

2. For private data, a way could be to create a t_linklist in your object structure, and manage your t_model with it. You will have to care about memory ownership and to release accordingly. Of course, if the number of t_model is constant and known at compile time, you could simply use an array of pointers.

3. “get access to those 5 structures in the rest of my program?” An external is a “bundle” for Mac and a “DLL” for windows. That’s not really a complete program. Do you mean “in other methods of my external” or “in other externals in Max/MSP”?

4. Take care to be consistent with libraries. I mean don’t mix standard malloc and Max/MSP API without any good reason.

5. Your problem is much more about generic techniques employed for Max/MSP objects than read/write features. IMHO make an example without. It should be easier to understand, and easier to explain.

#270948
Nov 12, 2013 at 8:29am

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.

#270964
Nov 12, 2013 at 8:38am

Actually it looks to work even with the warning. Thank you a lot!

#270965
Nov 12, 2013 at 9:05am

Use sysmem_newptr exactly as malloc (use sysmem_freeptr instead of free). To avoid warnings, you need to cast the returned pointer.

t_toto *p = (t_toto *)sysmem_newptr(sizeof(t_toto));

PS:

I created a repository here ( https://github.com/nicolasdanet/Flop ) as a kind of FAQ. It provides few more examples than those provided with the SDK (suggestions are welcomed).

Personnaly when i have questions, i look first into the SDK examples, later into open sourced projects as Jamoma, TapTools, and in the HoaLibrary since few weeks ago ;-)

https://github.com/tap/TapTools

https://github.com/jamoma/JamomaMax/tree/master/source

https://github.com/CICM/HoaLibrary/tree/master/Max

#270968
Nov 12, 2013 at 11:04am
#270999

You must be logged in to reply to this topic.