I've written a Mathematica package (see here) which uses WSTP to call a C/C++ library. Some possible user-errors are known by the package and can be detected and reported by the front-end package code. However, some user-errors are reported by the C library and must be sent on to Mathematica; these error messages are not known a-priori, and the errors cannot be detected by my package itself.
This seems incompatible with the standard way to report package errors, using Message. For example, if the package function myFunc accepts positive integers, the canonical way to handle this is:
myFunc::badarg = "First argument must be a positive integer"
myFunc[x_Integer] :=
If[ x<0,
(Message[myFunc::badarg]; $Failed),
...
]
(* of course there are more elegant ways to handle this usign patterns *)
The result looks like this in Mathematica:
In this example, we see the message in myFunc::badarg is fixed, and set a-priori.
In theory, even my WSTP functions can be given messages of this kind;
:Begin:
:Function: my_C_func
:Pattern: myFunc[x_Integer]
:Arguments: { x }
:ArgumentTypes: { Integer }
:ReturnType: Manual
:End:
:Evaluate:
myFunc::badarg = "First argument must be a positive integer"
Still, these error messages are fixed.
But now consider when my_C_func involves an error detected by the internal C library:
void my_C_func(int x) {
try {
library_func(x);
WSPut...
} catch(string err) {
// must send 'err' back to Mathematica
WSPut...
}
}
I would like to 'channel' err to the front-end, to report it like I would the myFunc::badarg error message. Unfortunately, Message[] accepts symbol::tag which is a-priori set, and we don't know what message err contains.
Is that at all possible? Otherwise, how can I fake the look of Message?
Currently, my hacky solution is to completely forego using Message, instead using Echo.
// must send 'err' back to Mathematica
WSPutFunction(stdlink, "EvaluatePacket", 1);
WSPutFunction(stdlink, "Echo", 2);
WSPutString(stdlink, err);
WSPutString(stdlink, "Error ");
WSEndPacket(stdlink);
WSNextPacket(stdlink);
WSNewPacket(stdlink);
WSPutSymbol(stdlink, "$Failed");

