7
$\begingroup$

What is the simplest way to throw away all expressions waiting to be read on a loopback link, effectively resetting the link?

I am building an expression on a loopback link using the C MathLink interface. If the operation succeeds, I want to send the expression to stdlink. If it fails, I need to clear the loopback link. What is the recommended way to do this?

$\endgroup$
6
  • $\begingroup$ Can't you just call MLClose on your current loopback link and then open a new loopback link? $\endgroup$ Commented Jan 28, 2013 at 8:23
  • $\begingroup$ Have you tried what happens when you pass NULL as dst in MLTransferToEndOfLoopbackLink? Apart from that it seems there is no way to clear a LoopbackLink. @ToddGaylay can you reveal what you would do? $\endgroup$
    – halirutan
    Commented Jan 28, 2013 at 9:38
  • $\begingroup$ Did you mean @Todd Gayley ? (yes, youd did) $\endgroup$
    – Yves Klett
    Commented Jan 28, 2013 at 15:40
  • $\begingroup$ @YvesKlett Yes and oops, I see my typo now. Thanks. $\endgroup$
    – halirutan
    Commented Jan 28, 2013 at 15:50
  • $\begingroup$ @Leonid I think I can, but I never went into MathLink this deep, and I was hoping for some reassurance that this is the "right" way to do it (i.e. how a loopback link was really meant to be used). $\endgroup$
    – Szabolcs
    Commented Jan 28, 2013 at 16:31

1 Answer 1

9
$\begingroup$

Using NULL as the destination link, as in MLTransferExpression(NULL, loop); is indeed the "correct" way to do this.

One small caveat: You cannot use that technique if you have not built a complete expression on the loopback link. For example, if you are building a complicated expression on the loopback link bit by bit, then decide halfway through to bail out and not use the result you have been building, then you would just want to close the loopback link to discard it. A simple example:

// Promise to put 100 elements:
MLPutFunction(loop, "List", 100);
int succeeded = TRUE;
for (int i = 0; i < 100; i++) {
    ...
    if (someTest) {
        succeeded = FALSE;
        // Bail out before putting all 100 promised elements.
        break;
    } else {
       MLPutInteger(loop, someInt);
    }
}

if (succeeded) {
    MLTransferExpression(stdlink, loop);
} else {
    // *** BAD ***  Haven't put a complete expression on the link,
    // so this will not work to drain the link:
    MLTransferExpression(NULL, loop);
    ... send different result on stdlink
}

If you are doing something like the above, it's better to accumulate the parts of the final expression on the link as separate expressions, then wait until the loop is done to build the final expression:

int count = 0;
for ( ; count < 100; count++) {
    ...
    if (someTest) {
        break;
    } else {
       MLPutInteger(loop, someInt);
    }
}

if (count == 100) {
    // Loop ran to completion; send a list containing all the elements
    // that were stored on the loopback link.
    MLPutFunction(stdlink, "List", 100);
    MLTransferToEndOfLoopbackLink(stdlink, loop);
} else {
    ... send different result on stdlink
}

In this way, you never have a partial expression on the loopback link.

But you can avoid all these considerations by simply opening and closing your loopback link every time your function is called. This could have an impact on performance if your function runs very quickly and is called many times. It costs about .00001 seconds on my machine to open and close a loopback link.

$\endgroup$
1
  • 1
    $\begingroup$ It sounds like I need to close/open the link then because I have half-built expressions. The performance hit is acceptable in this case. $\endgroup$
    – Szabolcs
    Commented Jan 28, 2013 at 20:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.