8
$\begingroup$

I have written numerous WSTP applications that take data from Mathematica, manipulate it in combination with data retrieved from other sources, and then return it to Mathematica. See for example https://github.com/MichaelSternNYC

All of these have been set up for a single interaction -- Mathematica calls wstpfunction[var1_Integer, var2_Integer] (or whatever) and this is received within C++ as void wstpfunction(int var1, int var2) (or whatever). The C++ code does what it needs to and then returns data to Mathematica with WSPutString() or one of its sister functions. The C++ application then terminates, though the WSTP link can be left installed, which speeds things up if wstpfunction[] is called again. Though the link remains valid, the program stops running after returning its output and must be restarted when called again. This is important because the value of any static variables is lost between calls.

My current task involves repeated use of a subscription to an outside data service, and I need certain information to remain resident in the WSTP program between calls. How might one craft a WSTP program that doesn't quit until asked, and which can accept new input from Mathematica at any time?

--

psuedo-code for the WSTP program

static int holder = 0;

// This is our entry point
void wstpfunction(int var1, int var2)
{
     holder = holder + var1 + var2;
     WSPutInteger(holder)
}

This code would work, but would not save the value of holder between runs.

$\endgroup$
  • 1
    $\begingroup$ I am confused by your question. A standard installable MathLink program provides a number of functions that will be callable from Mathematica. Calling these function does not cause the MathLink program to quit. To make it quit, you need to somehow terminate it explicitly. Can you explain in more detail why your program quits at all? I don't quite follow when you say "the value of any static variables is lost between calls". Perhaps a short example will help. $\endgroup$ – Szabolcs Sep 15 '16 at 18:59
  • $\begingroup$ I looked (very briefly!) at github.com/MichaelSternNYC/msBBGgetHistory at I still don't see why it should quit. You seem to be doing things the standard way. I didn't compile it. Does it crash by any chance?? $\endgroup$ – Szabolcs Sep 15 '16 at 19:05
  • $\begingroup$ @Szabolcs No crash; see simple example above. Is there something I should be doing different in the template file, I wonder? $\endgroup$ – Michael Stern Sep 15 '16 at 19:06
  • $\begingroup$ You didn't answer my question. You say "The C++ application then terminates". Why does it terminate? It should not normally terminate. Or is that your question as well? $\endgroup$ – Szabolcs Sep 15 '16 at 19:09
  • $\begingroup$ @Szabolcs In my trivial example above, wstpfunction(int var1, int var2) is the entrypoint specified in the template file. If I create a loop within wstpfunction, it doesn't accept new input and effectively hangs. If I don't create a loop, it gets to the end and terminates. If I call wstpfunction[] again from Mathematica, it will run but the value of the static variables (holder in this example) has been lost. $\endgroup$ – Michael Stern Sep 15 '16 at 19:26
7
$\begingroup$

There are a number of misunderstandings in your question.

The C++ application then terminates, though the WSTP link can be left installed, which speeds things up if wstpfunction[] is called again. Though the link remains valid, the program stops running after returning its output and must be restarted when called again.

A installable MathLink/WSTP program does not stop running (quit) after calling a function it provides. It keeps running until it is Uninstalled, or until it is explicitly terminated in some way.

If the program quits for some reason, for example it crashes, then the link becomes invalid immediately.

This is important because the value of any static variables is lost between calls.

This is not correct. For as long as the program keeps running, both global variables (what you show in the example) and static variables maintain their value. You can try this with a small example (see at the end of the post).

Note that in your example you are using static in front of a global variable. This use of static specifies internal linkage, not a static variable.

My current task involves repeated use of a subscription to an outside data service, and I need certain information to remain resident in the WSTP program between calls. How might one craft a WSTP program that doesn't quit until asked, and which can accept new input from Mathematica at any time?

Exactly in the way you show in your example. Use a global variable. MathLink programs don't quit on their own unless you terminate them explicitly.


Example program

The template file:

:Begin:
:Function:  add
:Pattern:   add[x_Integer]
:Arguments: {x}
:ArgumentTypes: {Integer}
:ReturnType:    Manual
:End:  

:Begin:
:Function:  get
:Pattern:   get[]
:Arguments: {}
:ArgumentTypes: {}
:ReturnType:    Integer
:End:

C file:

#include <mathlink.h>

int num = 0;

void add(int x) {
    num += x;
    MLPutSymbol(stdlink, "Null"); // return nothing
}

int get() {
    return num;
}

#if WINDOWS_MATHLINK

#if __BORLANDC__
#pragma argsused
#endif

int PASCAL WinMain( HINSTANCE hinstCurrent, HINSTANCE hinstPrevious, LPSTR lpszCmdLine, int nCmdShow)
{
    char  buff[512];
    char FAR * buff_start = buff;
    char FAR * argv[32];
    char FAR * FAR * argv_end = argv + 32;

    hinstPrevious = hinstPrevious; /* suppress warning */

    if( !MLInitializeIcon( hinstCurrent, nCmdShow)) return 1;
    MLScanString( argv, &argv_end, &lpszCmdLine, &buff_start);
    return MLMain( (int)(argv_end - argv), argv);
}

#else

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

#endif

Test it:

Install["example"]

get[]
(* 0 *)

add[1]

get[]
(* 1 *)

add[100]

get[]
(* 101 *)
$\endgroup$
  • $\begingroup$ Thanks for your patience in answering this. I was indeed nuking the persistent variables elsewhere in my code. $\endgroup$ – Michael Stern Sep 16 '16 at 11:22

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.