Some sort of array of dictionaries?

    Mar 26 2010 | 6:14 pm
    Hi there,
    Still quite new to writing externals, although I've managed to create a few that I'm already using (read: testing) in real-life situations! So slowly building some understanding of all this. I realised I'm better off asking this question on the forum that creating any wonderful misconceptions of my own:
    What would be the preferred method for implementing, what i see as being, an array of dictionaries. I.e. data than can be looked up according to index then key.
    An example of data structure:
    index: 0 key: "name" value: "frank" key: "age" value: 28 key: "gender" value: "male"
    index: 1 key: "name" value: "rebecca" key: "age" value: 12 key: "gender" value: "female"
    The reason why I'm imagining some sort of a array of dictionaries is that the data structure could easily be updated to something else (in this structure, to for example more key/value pairs) without a huge amounting of re-coding, plus it could lead to more readable code in general.
    How would you go on about implement something like this in maxsdk-world? Thanks for any insights - and sorry for my noobness,

    • Mar 26 2010 | 11:16 pm
      you can just do exactly what you are suggesting... make an array of dictionaries.
      int num_dictionaries = 5;
      t_dictionary** dict_array = (t_dictionary*) malloc(sizeof(t_dictionary*) * num_dictionaries);
      // actually these days t_dictionary* dict_array[num_dictionaries] should be fine
      for (int i = 0; i != num_dictionaries; ++i)
        dict_array[i] = dictionary_new();
    • Mar 27 2010 | 4:42 pm
      Hi Brian,
      Thanks a lot, I will go try this out now. If you happen to have a minute, there's a few things in your example code that a I'm trying to understand, newcomer that I am:
      - What are the circumstances when one uses a pointer to a pointer as in your example? I haven't come across this yet.
      - when does one use malloc, as in your code, and when to use sysmem_newptr()?
      Thank you once again, I'll go give it a shot. Best regards, antwan
    • Mar 28 2010 | 4:19 am
      second part first.
      - when does one use malloc, as in your code, and when to use sysmem_newptr()?
      in a max extension, basically always use sysmem_newptr(). this is a mistake on my part.
      - What are the circumstances when one uses a pointer to a pointer as in your example? I haven't come across this yet.
      first off, realize that a pointer to some kind of data and an array of that kind of data are almost but not quite the same in C. So an array of ints is almost but not quite the same as a pointer to an int. in code:
      int[5] int_array;
      int_array[0] = 0;
      int_array[1] = 1; // etc...
      // but also:
      *(int_array + 2) = 2;
      // with a pointer:
      int* int_ptr = sysmem_newptr(sizeof(int) * 5); // NOTE you should be checking for an error here
      *int_ptr = 0;
      *(int_ptr + 1) = 1; // etc...
      // but also:
      int_ptr[2] = 2;
      in other words, the compiler will translate var[2] into *(var + 2) for you. Furthermore, &var[2], the memory address of the second element in the array, is equal to var + 2.
      I say that pointers and arrays are almost but not quite the same for 2 reasons: - You can reassign a pointer to another address in memory, but you can't reassign an array like that. - More importantly, a pointer is probably acquired in such a way that requires you to explicitly free the memory. Arrays are defined within a specific scope and are automatically destroyed when that scope ends.
      getting back to max, i'm using a pointer to a pointer because one only deals with max' dictionaries (and hashmaps, etc) through pointers. the documentation specifies the structs as "opaque"; in other words, you should never allocate a t_dictionary yourself, which you would be doing if you tried to do either of these things:
      t_dictionary my_dictionary;
      t_dictionary my_dictionary_array[5];
      Instead, you always want to get a pointer to a dictionary using dictionary_new(). So if you're making an array of pointers, you've now got... a pointer to a pointer.
      If you make an array of pointers to t_dictionarys, realize that even though the array will get automatically destroyed when it goes out of scope, it's an array of pointers. Only the pointers themselves will get automatically destroyed. You still have to manually free what each of those pointers points to.
      I have to admit that I haven't actually used this newfangled Max5 dictionary structure. Taking a look at its documentation, the following point seems relevant and worth repeating: when you free a dictionary, it frees everything it refers to, so watch out for double frees.
    • Mar 29 2010 | 11:47 am
      Thanks so much for taking the time to explain. I surely understand it all better now. And it's all working, so I'm good to go forth :)
      Cheers, antwan