min-devkit outlet crash with prepended string
I just started working with the min-devkit a little bit and I am running into a weird crash I don't quite understand (see code snippet below). I am on Sequoia 15.1.1 on a 2023 M3 using Max 8.6.5.
If I send something out an outlet, starting with a string followed by a single number (e.g. float), that works. Anything else seems to cause a crash.
What I am trying to do is add a string before a list of floats so I can use [route] in max to further process the output.
Furthermore, when I use a string followed by atoms
model.send("data", data_atoms)
I get an error stating:
No matching member function for call to 'push_back'
referring me to c74_min_outlet.h line 282
// utility: queue an argument of any type for output
template <typename argument_type>
void queue_argument(const argument_type& arg) noexcept
{
m_accumulated_output.push_back(arg);
}
this clearly treats m_accumulated_output as a vector since we are using the push_back() to add a value to the end of it. However, if I look at the type of m_accumulated_output it is of type atoms. (see line 434 in c74_min_outlet.h)
If I go to c74_min_atom.h it clearly states on line 319 that:
// We don't own the array of atoms, so we cannot do these operations:
// insert
// erase
// push_back
// push_front
// pop_front
// pop_back
I might have a fundamental misunderstanding here, but it looks like that if we deal with atoms we can't use .push_back(), but in queue_argument() from c74_min_outlet.h (line 282) we clearly use .push_back() to try to add something to atoms.
So, long story short: what is the correct way of sending something like:
std::vector<float> data = {....};
std::string routing = "data";
to_outlet.send(routing, data);
so in max I can use [route data] to process the output?
Thanks so much for your help!!!
Here are the different ways I have tried to use this and the results:
// Handle "bang" message
message<> bang{this, "bang", "Outputs the data.",
MIN_FUNCTION {
std::vector<float> entry = {7.4f};
std::vector<float> entries = {1.0f, 2.0f, 3.0f};
atoms data(entries.size());
data = to_atoms(entries);
//use vector directly => crash
model.send(entries); // => crash
//convert vector to atoms => works
model.send(data); // ==> works
model.send(to_atoms(entries)); // ==> works
//use string with float => works
model.send("data", 1.45f); // ==> works
//use string with atoms (single float) => crash
model.send("data", to_atoms(entry)); // ==> crash
//use string with float vector => crash
model.send("data", entries); // ==> crash
//use string with atoms (multiple floats) => crash
model.send("data", data); // ==> crash
return {};
}
};
Yep, there are quite a few issues in terms of type safety in the current implementation of min::outlet::send
. This is what I tend to do when I need to output keyword + vector:
message<> bang{this, "bang", MIN_FUNCTION {
std::vector entries{1.0f, 2.0f, 3.0f};
atoms atms{"data"};
atms.reserve(entries.size() + 1);
atms.insert(atms.end(), entries.begin(), entries.end());
outlet_main.send(atms);
return {};
}};
The atms.reserve(entries.size() + 1);
is redundant here, but it's good practice if you don't know the size of the output beforehand
Thanks! that works perfectly.