how to retrieve a C string from the list input of an external?

Rainer.Buerck's icon

Maybe someone can help me with this: I want to obtain a C string from a list sent to the list inlet of a Max external. The list sent to the external is produced by packing an int and a message (sent from a message box) into a list.

So far I have used lists consisting of ints and floats. To achieve this, the function of my external looks like this:

void input_list (MyObject *x, t_symbol *msg, short argc, t_atom
    * argv)
{

x being a pointer to the struct of myObject, argc indicating the number of elements of the received list and argv containing the elements of the list.

In order to obtain the elements of a list consisting of different types of data, properly, the types of the particular elements have to be specified. For example, if I want to process a list consisting of an int and a float, I will write:

if ((argc == 2) && (argv[0].a_type == A_LONG) && (argv[1].a_type
    == A_Float))
{
    //.... process the data        

Which means: if the number of elements of the list equals 2 and the first element is an int and the second element is a float, then process the data.

Now my question is: how can I obtain a C string from a list consisting of an int and a string (produced by the message box)?

I think the code will look something like:

if ((argc == 2) && (argv[0].a_type == A_LONG) && (argv[1].a_type
    == A_SYM))
{

but how can I retrieve a C string from this and copy it into an array maybe specified like this:

char my_String [31]; ?

Luigi Castelli's icon

Hi there,

Before I give you the solution change the following:

1) define your function like this:void input_list(MyObject *x, t_symbol *msg, long argc, t_atom *argv);
Don't use short for argc. Use long.

2) don't access atom struct fields directly.
The new Max/MSP API provides accessor functions such as:t_atom_long atom_getlong(const t_atom *a),t_atom_float atom_getfloat(const t_atom *a) andt_symbol *atom_getsym(const t_atom *a)

If you need to get the atom type you may use:long atom_gettype(const t_atom *a)

To answer your question:
if ((argc == 2) &&
(atom_gettype(argv) == A_LONG) &&
(atom_gettype(argv+1) == A_SYM))
{
long my_long;
t_symbol *my_sym;
char my_String[31];
my_long = atom_getlong(argv);
my_sym = atom_getsym(argv+1);
strncpy_zero(my_String, my_sym->s_name, sizeof(my_String));
}

At this point my_String should contain what you want.

Keep in mind that I coded it off the top of my head without testing.
So please run the code and make sure it produces the expected result.

Cheers.

- Luigi

Rainer.Buerck's icon

Hi Luigi,

thanks a lot. I haven't had time to try it yet, but I will let you know tomorrow if it worked.

Cheers,

Rainer

Rainer.Buerck's icon

Hi again,

I am just trying your suggested code. However, there seems to be a problem with the 'strncpy_zero‘ function. I get the following error:

Implicit declaration of function 'strncpy_zero' is invalid in C99

Rainer.Buerck's icon

OK, it works now. I forgot

#include "ext_strings.h"

Thanks a lot!

Cheers,

Rainer

Rainer.Buerck's icon

Hi again,

I don’t know if I should open a new topic for this.

The resaon for wanting to receive a list including an int and a C string is that I want to open a data file for my external by using the function

path_opensysfile , for which I require a path ID and a file name.

My external works with lots of arrays which I save as data files. To load these files, I have been using the function open_dialog so far, but this means that I always have to click on the „Open File“ menu item of my object and select the file in the dialog window. To save time I would like to have the option of also letting my external automatically load a specific file when the patcher window (containing this external) is loaded and opened. I am trying to make loadbang send a list with the path ID and file name to the external and then use path_opensysfile to load the file.

This works on my MacPro (OS 10.6.8), but it doesn’t really work on my MacBook (OS 10.8.5). There is a strange behaviour which I can’t explain. If I launch my patcher and send the list with the path ID and filename to my external to load the file, I get an error. But if I first click on the „Open File“ menu item of my external, calling the open_dialog function, things are different. It dosen’t really matter if I then select a file in the dialog window or if I just press „Cancel“. If I then send the list including the path ID and filename to my external, it will load the file. Can you explain ths?

I find the Max6 API Reference quite confusing. I haven’t managed to find all the file handling functions in it. Are they still there? This documentation isn’t very clear, and there is no index including all terms.