5
$\begingroup$

My WSTP package includes some C++ calculations which can take a long time. I'd therefore like to display a ProgressIndicator during this calculation, the progress of which is updated by a C++ loop.

The obvious technique doesn't appear to work:

void sendProgress(qreal prog) {

    // send new packet to kernel
    WSPutFunction(stdlink, "EvaluatePacket", 1);

    // show progress bar
    WSPutFunction(stdlink, "ProgressIndicator", 1);
    WSPutReal64(stdlink, prog);

    // a new packet is now expected; caller MUST send something else
    WSEndPacket(stdlink);
    WSNextPacket(stdlink);
    WSNewPacket(stdlink);
}

void myExpensivFunc() {

    for (...)
        sendProgress(...)
        // includes sleeps

    // send actual result
    WSPutInteger(...)

}

Though running without error, a ProgressIndicator never appears, even if sendProgress is called just once. This is the technique I use to send intermediate Echo and Message expressions to the kernel before the ultimate function result, so I'm surprised it failed for ProgressIndicator.

So I suspect maybe ProgressIndicator will need to be invoked in the kernel, possibly with something like

wrapperFunc[] := 
  Module[{i=0},
    Monitor[
      myExpensiveFunc[i],
      ProgressIndicator[i]
    ]
  ]

but I'm still perplexed how I could update i from C++ with intermediate values, say by using EvaluatePacket.

Is this at all possible?

$\endgroup$
  • 1
    $\begingroup$ Try setting the value of a Mathematica variable periodically from your C code. In an initial test, you can hard-code the name of that variable and do not use Module because it will rename it. Then simply hook up the variable to a progress indicator: ProgressIndicator[Dynamic[progressVar], {min, max}]. Did this work? If not, please post a complete compilable example of what you tried and I'll take a look. I do not have the time to write an example from scratch. $\endgroup$ – Szabolcs Mar 18 at 9:32
  • $\begingroup$ My project is QuESTlink, but I'll create a dedicated MWE Github repo. But first; how can I set the variable from C, without my C function returning? I can't tell whether WSTP even allows evaluation of an assignment expression, like a=1. $\endgroup$ – Anti Earth Mar 18 at 13:56
  • $\begingroup$ I recommend reading all of the old tutorial: edenwaith.com/development/tutorials/mathlink/ML_Tut.pdf Look at section 1.6 in particular. Any expression can be evaluated, it does not matter if it is Set or not. $\endgroup$ – Szabolcs Mar 18 at 13:59
  • $\begingroup$ The thing is that I would not be able to answer your question without constructing an MWE myself. This is why I asked for one. I don't use MathLink often enough to be able to give a precise answer without trying it out. $\endgroup$ – Szabolcs Mar 18 at 13:59
  • $\begingroup$ Thanks for the link - it's precisely my solution above :) I hadn't realised Set was getting called, but that should do the trick. I'll test this in a MWE and report back $\endgroup$ – Anti Earth Mar 18 at 14:07
2
$\begingroup$

As per Szabolcs's suggestion, this can be done by using Set, to dynamically update a variable used by a ProgressIndicator evaluated in Mathematica. See here for a buildable demo.

The relevant code (using the variable names used above, which differ from the demo)...

MyPackage.m

wrapperFunc[] := Monitor[
    i=0; myExpensiveFunc[]
    ProgressIndicator[i]
]

my_backend.c

void sendProgress(double prog) {

    WSPutFunction(stdlink, "EvaluatePacket", 1);

    // i = prog
    WSPutFunction(stdlink, "Set", 2);
    WSPutSymbol(stdlink, "MyPackage`Private`i");
    WSPutReal64(stdlink, prog);

    WSEndPacket(stdlink);
    WSNextPacket(stdlink);
    WSNewPacket(stdlink);
}


void myExpensivFunc() {

    for (double prog ...)
        sendProgress(prog);

    // send actual result
    WSPutInteger(...)

}
| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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