Message Boards Message Boards

0
|
2536 Views
|
4 Replies
|
0 Total Likes
View groups...
Share
Share this post:

Question about "printing" from a C program to a WSTP link

I have modified a legacy C program so that it can be called as a function from Mathematica using the WSTP template mechanism. The original C program, however, contained multiple printf statements to report errors and other diagnostic information; these don't appear anywhere, obviously, because they are not talking to the WSTP link. When I replace these p by calls to WSPutString, the diagnostic text does indeed appear in my Notebook, BUT each call to WSPutString pauses execution of the C program and I have to call the function repeatedly from my Notebook, once for each line of diagnostic output and then once more for the final return value, which is an array of numbers. Wondering how to fix this pausing behavior. Here's what my code looks link:

// WSTP template

:Begin:  
:Function:      function  
:Pattern:       function[....]  
:Arguments:     {...}  
:ArgumentTypes: {....}  
:ReturnType:    Manual  
:End:  

#include <stdio.h>  
#include "wstp.h"  

void function(.....)  
{  

 // Calculate a bunch of stuff, putting the results in an array named "result"  
.....

//  While we're calculating this stuff, the original C program used printf calls to output diagnostic text strings  
//  at various points in the program  
//  printf("%s\n", diagostic_text);

//  These messages do not appear in the Mathematica notebook, so instead I use a Wolfram C function:  
....

  WSPutString(stdlink,diagtxt1);  
.....

  WSPutString(stdlink,diagtxt2);  
....

//  Return the results of the calculation

  WSPutReal64List(stdlink, result, size);  
  return;         
} 

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

Now in my Mathematic notebook, I have to call the function many times. For example, if there are 43 "printf" statements before the C program returns the final result, I have to do this:

Install["./function"]

Table[function[....], 44]
POSTED BY: Brian Aull
4 Replies

Until you debug it, you might also want to return something like 0 if the code does not compute an answer to avoid an error.

POSTED BY: Neil Singer

As an alternative, you can append all diagnostic messages into one string and just return a list of the diagnostic string and the result list.

In this approach, you would do a sequence of sprintf() calls.

sprintf(Buffer,"diag1\n");
sprintf(Buffer + strlen(Buffer),"diag2\n");

or track and use the length returned by sprintf().

Regards,

Neil

POSTED BY: Neil Singer

Thanks, Neil. That works great if I know ahead of time that "43" is the right length of the diagnostic text list, which is true if the program encounters no error conditions. If, however, the calculations need to be terminated, for example, due to numerical convergence problems, I get a list of diagnostics that is quite a bit shorter than "43" and no "result" at all. In this case, the invocation in Mathematica returns an error: LinkRead::linkep: An unexpected end of packet was received.

POSTED BY: Brian Aull

Brian,

I would combine all the strings into a list and return them to Mathematica along with your result. The result would be in this form: List[List[diag1,diag2,...], List[Real1,Real2,Real3,...]]

WSPutFunction(stdlink, "List", 2);
WSPutFunction(stdlink, "List", 43);
WSPutString(stdlink,diagtxt1);
...
WSPutString(stdlink,diagtxt43);
WSPutReal64List(stdlink, result, size);

You can read about it in this tutorial. Search for

You can use WSTP functions to create absolutely any Wolfram Language expression. The basic idea is to call a sequence of WSTP functions that correspond directly to the FullForm representation of the Wolfram Language expression.

Regards,

Neil

POSTED BY: Neil Singer
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract