Right, this was a bit hard to debug. The code is mostly fine, but the issue is here:
oscpkt::Message::ArgReader arg(msg);
in include/oscpkt.hh
you can see that there are two possible constructors for ArgReader()
. The one you are trying to use is:
ArgReader(const Message &m, ErrorCode e = OK_NO_ERROR) : msg(&m), err(msg->getErr()), arg_idx(0) {
if (e != OK_NO_ERROR && err == OK_NO_ERROR) err=e;
}
But you are passing msg
, which is a Message*
. So, this in turns calls a constructor of Message
which can make an object from a Message*
:
Message(Message* msg) :
time_tag(msg->time_tag),
address(msg->address),
type_tags(msg->type_tags),
arguments(msg->arguments),
storage(msg->storage),
err(msg->err)
{}
This means that the first argument passed to ArgReader(const Message &m, ErrorCode e = OK_NO_ERROR))
is not your Message* msg
, but a temporary object that is created by the above mentioned constructor of Message
. arg
will contain a pointer to this temporary object, but the temporary object goes out of scope as soon as the constructor to ArgReader()
returns, so the pointer stored in arg
is invalid, and when your code tries to access it, it gets a segmentation fault. The fix is to pass to ArgReader()
an actual object and not a pointer. This can be done easily by dereferencing the pointer:
oscpkt::Message::ArgReader arg(*msg);
the constructor will then store a pointer to the object (i.e.: it will store the same value contained in msg
), which will stay valid for the duration of the life of arg
, so that everything works fine.
To avoid confusion in the future, you could instead use the copy constructor for ArgReader
, defined as:
ArgReader(const ArgReader &other) : msg(other.msg), err(other.err), arg_idx(other.arg_idx) {}
so your code would become:
oscpkt::Message::ArgReader arg(msg->arg());
Here's an example that works for me:
if(msg && msg->match("/test")){
//This works ok!
oscpkt::Message::ArgReader arg(msg->arg());
rt_printf("number of args in message: %i\n", arg.nbArgRemaining());
int intArg;
float floatArg;
intArg = floatArg = -1;
if (arg.isInt32())
arg.popInt32(intArg); //also tried with ending .isOkNoMoreArgs(), same result
if (arg.isFloat())
arg.popFloat(floatArg); //also tried with ending .isOkNoMoreArgs(), same result
if(arg.isOkNoMoreArgs())
rt_printf("i: %d, f: %f, rem: %d\n", intArg, floatArg, arg.nbArgRemaining());
else
rt_printf("err\n");
}
oscPipe.writeRt(msg); // return the pointer to the other thread, where it will be destroyed