4
$\begingroup$

In the compile process of a C function written by using wstp.h library (Mathematica 11.3), an error (Error LNK2019: unresolved external symbol WSEvaluate referenced in function) is shown.

I opened wstp.h file. For each function started by WS, there is an ML equivalent (For example, #define MLGetData WSGetData), but for WSEvaluate there is nothing. I added a line- #define MLEvaluate WSEvaluate- but it did not work. Can you please guide me to solve this compile error?


Here is a C fucntion which produces the mentioned error:

#include "wstp.h"
#include <stdlib.h>
#include <windows.h>

extern int WSMain(int, char **);
#ifdef WINDOWS_WSTP
extern HWND WSInitializeIcon(HINSTANCE hinstCurrent, int nCmdShow);
#endif

extern void ShowMyMessages();
void ShowMyMessages()
{
    WSEvaluate(stdlink, "Message[ShowMyMessages::msg]");
    WSNextPacket(stdlink);
    WSNewPacket(stdlink);
    WSPutSymbol(stdlink, "$Failed");
}

#if WINDOWS_WSTP

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 (!WSInitializeIcon(hinstCurrent, nCmdShow)) return 1;
    WSScanString(argv, &argv_end, &lpszCmdLine, &buff_start);
    return WSMain((int)(argv_end - argv), argv);
}

#else

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

#endif

And here is its .tm code

void ShowMyMessages P(());

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

:Evaluate: ShowMyMessages::msg = "Hello"
:Evaluate: ShowMyMessages::usage = "ShowMyMessages[]"

And here its compile commands

SET CL=/nologo /c /DWIN32 /D_WINDOWS /W3 /O2 /DNDEBUG
SET LINK=/NOLOGO /SUBSYSTEM:windows /INCREMENTAL:no /PDB:NONE kernel32.lib user32.lib gdi32.lib
WSPREP showMessage.tm -o showMessagetm.c
CL showMessage.c showMessagetm.c
LINK showMessage.obj showMessagetm.obj wstp64i4m.lib /OUT:showMessage.exe

This is the message generated by the compiler:

showMessage.obj : error LNK2019: unresolved external symbol WSEvaluate referenced in function ShowMyMessages
showMessage.exe : fatal error LNK1120: 1 unresolved externals
$\endgroup$
  • $\begingroup$ Can you give a complete minimal example that reproduces the error? WSEvaluate is not part of the WSTP interface but it is present in the C code generated by the wsprep program from a .tm file. It would seem that you are not linking wsprep's output into your program. $\endgroup$ – Szabolcs Sep 6 '18 at 6:52
  • $\begingroup$ Don't refer to the docs. objdump -tC libWSTP64i4.so | grep WSEvaluate yields nothing. $\endgroup$ – kh40tika Sep 6 '18 at 7:07
  • $\begingroup$ @kh40tika In this case there is no bug. The documentatio does state that this function is only available when using wsprep/mprep. It's not supposed to be present in that library. It is generated by mprep (you can see it in the code generated by mprep). $\endgroup$ – Szabolcs Sep 6 '18 at 7:43
  • $\begingroup$ @kh40tika Also, it is quite natural that it would not be generally available as what it does is evaluate code. MathLink on its own can't do that: all it does is transfer expressions. Evaluation makes sense if one of the endpoints of the link is the Mathematica kernel. That is the situation in the case of installable MathLink programs. $\endgroup$ – Szabolcs Sep 6 '18 at 7:45
  • $\begingroup$ If you come up with a complete solution based on my answer, please post it and feel free to accept it. It will be useful for people. Self-answers are always encouraged. $\endgroup$ – Szabolcs Sep 6 '18 at 15:10
3
$\begingroup$

I did not have the time to construct a complete solution for you, but I looked at wstp.h and at the output of wsprep. Here's what I found:

wstp.h has no WSEvaluate declared. It has MLEvaluate instead.

wsprep is supposed to output the definition of WSEvaluate (while wstp.h is supposed to have the declaration). But wsprep outputs neither WSEvaluate nor MLEvaluate. It outputs PREPEvaluate, which looks like a bug to me. I'd try #define WSEvaluate PREPEvaluate and add a declaration manually, but I'd expect this workaround to break with the next Mathematica release.

The documentation only talks about WSEvaluate (for wstp.h). Three places have three inconsistent things.


In comparison, mathlink.h and mprep are as expected: both have MLEvaluate, which is consistent with the documentation.


My personal opinion on this still hasn't changed:

MathLink was renamed to WSTP purely for marketing reasons. This move brought exactly zero technical benefits. However, it did create bugs, it did create additional work for developers (= a waste of time), and it did lead to many inconsistencies between the documentation and the actual state of things, as the ML->WS renaming seems to have been done separately in the actual code and in the documentation.

If you want to save yourself trouble, use the ML-prefix API, not the WS-prefix one. This has been in use for more than 25 years and is well tested. There is evidence that this, and not the WS-named equivalent, is being used internally (e.g. see the symbols in the kernel executable). LibraryLink only works with the ML-functions, not the WS ones. J/Link and .NET/Link did not change the MathLink naming in their API, and their C basis still uses ML-prefixed functions. Changing all this would be a pointless waste of time so I assume Wolfram won't do it, even if they say that ML deprecated.

Why would you choose the WS ones then? I understand that Wolfram tells you that the ML ones are deprecated, but I look at what they do, not what they say.

$\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.