Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have an Installable MathLink program written in C. I would like to use a custom message handler. At which point in the C source code should I call MLSetMessageHandler()?

The standard structure for such an installable MathLink program is this:

int main(int argc, char* argv[]) {
    return MLMain(argc, argv);
}

First I tried something like this:

/* does this look OK? */
void msghandler(MLINK link, int msg, int arg) {
    switch (msg) {
    case MLInterruptMessage:
    case MLAbortMessage:
        myabort();
        break;
    default:
        stdhandler(link, msg, arg);
    }
}

int main(int argc, char* argv[]) {
    MLSetMessageHandler(stdlink, (MLMessageHandlerObject) msghandler); /* <- wrong place to set it */
    return MLMain(argc, argv);
}

(I'm showing this code in full to also get some feedback on the structure of the message handler function.)

This doesn't work for two reasons:

  1. MLSetMessageHandler() fails and returns the code MLEDEAD, which I assume means that the link is not yet initialized. I suppose that's done in MLMain().

  2. MLMain() itself will call MLSetMessageHandler() and overwrite any previous one.

Question: Is there a simpler way to fix this than writing my own MLMain replacement (MLMain is generated by mprep)?

share|improve this question
    
Why can't you have a custom function to set your message handler and call it as a part of installing your function, after MlMain does this? –  Leonid Shifrin May 18 '13 at 22:58
    
You could also use a hack and define a MLSetMessageHandler macro using the C preprocessor, to effectively disable the code generated by mprep. Something like #define MLSetMessageHandler(x,y) and then #define MLSetMessageHandler(x,y,flag) MLSetMessageHandler(x,y) . The point is that you will use the second version with a (spurios) flag - say 0, and since the macro expansion is not recursive, the first version won't be used on the expanded result. –  Leonid Shifrin May 18 '13 at 23:05
    
Actually, the most economical way would be to define the macro as #define MLSetMessageHandler(link, handler) MLSetMessageHandler(link, (MLMessageHandlerObject) msghandler), and then you don't need to set it yourself - as long as this #define is included when you compile your files, it will automatically replace the call to MLSetMessageHandler that is present in generated MLMain(). This should answer both of your concerns at the same time. –  Leonid Shifrin May 19 '13 at 12:36
    
The standard way to define a message handler function is with the MLMDEFN macro, and I recommend that you use it: MLMDEFN(void, msghandler, (MLINK mlp, unsigned long message, unsigned long n)) { ... }. Note that the two parameters are longs. –  Todd Gayley May 20 '13 at 4:02
    
@ToddGayley and Leonid: Thanks! Otherwise does the handler look fine, calling stdhandler for everything except Interrupt and Abort? It was not clear to me which messages must be handled, and how. –  Szabolcs May 20 '13 at 4:18
show 7 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.