18
$\begingroup$

I need to write a C/C++ program and call some functions in Mathematica especially those like Solve or NDSolve. The problem is that in the Mathematica documentation it seems to me there is no mention about this.

There are plenty of details regarding how to create a C function and then call it from within Mathematica, but in my case I need the opposite.

Maybe I did not read well, but can you explain me how to do this?

$\endgroup$
18
$\begingroup$

Have a look at this;

http://reference.wolfram.com/mathematica/guide/MathLinkCLanguageFunctions.html

I haven't used it in C/C++ but it works fine in C# and Java. Basically you create a connection to a Mathematica kernel and then pass it native data types. Works nicely.

Here is some sample code in Java that I used when I first did this;

import com.wolfram.jlink.*;

public class SampleProgram {

public static void main(String[] argv) {

    KernelLink ml = null;

    try {
        ml = MathLinkFactory.createKernelLink(argv);
    } catch (MathLinkException e) {
        System.out.println("Fatal error opening link: " + e.getMessage());
        return;
    }

    try {
        // Get rid of the initial InputNamePacket the kernel will send
        // when it is launched.
        ml.discardAnswer();

        ml.evaluate("<<MyPackage.m");
        ml.discardAnswer();

        ml.evaluate("2+2");
        ml.waitForAnswer();

        int result = ml.getInteger();
        System.out.println("2 + 2 = " + result);

        // Here's how to send the same input, but not as a string:
        ml.putFunction("EvaluatePacket", 1);
        ml.putFunction("Plus", 2);
        ml.put(3);
        ml.put(3);
        ml.endPacket();
        ml.waitForAnswer();
        result = ml.getInteger();
        System.out.println("3 + 3 = " + result);

        // If you want the result back as a string, use evaluateToInputForm
        // or evaluateToOutputForm. The second arg for either is the
        // requested page width for formatting the string. Pass 0 for
        // PageWidth->Infinity. These methods get the result in one
        // step--no need to call waitForAnswer.
        String strResult = ml.evaluateToOutputForm("4+4", 0);
        System.out.println("4 + 4 = " + strResult);

    } catch (MathLinkException e) {
        System.out.println("MathLinkException occurred: " + e.getMessage());
    } finally {
        ml.close();
    }
}
}

The connection string argv should look something like this

String argv = "-linkmode launch -linkname 'C:\\Program Files\\Wolfram Research\\Mathematica\\8.0\\mathkernel.exe'";

http://reference.wolfram.com/mathematica/JLink/tutorial/WritingJavaProgramsThatUseMathematica.html

$\endgroup$
  • 1
    $\begingroup$ Could you provide a simple Java(or C#) program that calls Mathematica to solve an equation? I know that creating these type of examples do take time but in the long run maybe others could benefit from your experience. $\endgroup$ – jmlopez Apr 30 '13 at 18:59
  • $\begingroup$ Not a problem jmlopez. The standard Wolfram example is a good one I think. $\endgroup$ – Cam May 1 '13 at 1:05
  • 1
    $\begingroup$ @Andry I don't have any first hand experience with C/Mathematica links but it looks like you call it more like the putFunction method call in the Java. Have a look at this; reference.wolfram.com/mathematica/tutorial/… $\endgroup$ – Cam May 2 '13 at 22:52
  • 1
    $\begingroup$ I regret that I have to downvote this. The question asks about C/C++, but the solution is in Java! The link provided goes to the top level of MathLink, but the whole point of the question is that MathLink docs generally cover Mathematica -> C rather than the other way around. (I have a similar problem now, which brought me to this question.) $\endgroup$ – Eric Brown Aug 26 '13 at 1:50
  • 1
    $\begingroup$ If you could point me to the specific page that demonstrates the "round trip" in C that you have shown in Java, then I would be happy to eat crow. What I see on the Mathlink documentation is very high-level. $\endgroup$ – Eric Brown Aug 26 '13 at 5:33
9
$\begingroup$

The other answers ignore that you are asking about C or C++ (not C# or Java!)

Mathematica can be called from C (or C++) through the MathLink interface (recently renamed to WSTP). To learn it, I recommend reading this old MathLink tutorial by Todd Gayley:

Section 2 discusses what you are asking for: calling Mathematica from a C program rather than the reverse case (which is better covered in the official documentation)

You will find several example programs (like factor.c) in the directory opened by this command:

SystemOpen@
 FileNameJoin[{$InstallationDirectory, "SystemFiles", "Links", 
   "MathLink", "DeveloperKit", $SystemID, "MathLinkExamples"}]

It is also useful to experiment with setting up MathLink connections in pure Mathematica code. This will help you understand the basic procedure before you try to implement the same in C:

$\endgroup$
7
$\begingroup$

C Style

To Call Mathematica functions from C/C++ you need to use ML_ or WS_ functions. Mathematica is now "replacing" MathLink with WSTP. However function names are mostly similar. There are C style WSPutT functions that are used to send an input of type T to mathematica. and the output is fetched from mathematica using WSNextPacket and WSGetT functions. To use these accessing functions first a link needs to be established WSOpenArgcArgv. The C language Reference lists the functions that you will need to communicate with mathematica using C/C++

C++ (with mathematica++)

I was mostly interested to use mathematica from C++. So I developed one C++ library mathematica++ that uses template magic for easier interoperability between C++ and Mathematica. The usage example below is copied from the project page.

symbol x("x");
value  res;
std::string method = "Newton";

shell << Values(FindRoot(ArcTan(1000 * Cos(x)), List(x, 1, 2),  Rule("Method") = method));
shell >> res;
std::vector<double> results = cast<std::vector<double>>(res);
std::cout << results[0] << std::endl; // Prints 10.9956

With mathematica++ you declare a mathematica function using MATHEMATICA_DECLARE(FunctionName) and then use the function FunctionName in C++. Like in the example above FindRoot is being used to solve the equation. It builds an equivalent chain of WS_ functions on runtime. The template function cast<T> can be sued to cast mathematica returned results back to C++ STL types.

symbol i("i"); // declare mathematica symbol i
value result_list; // declare the variable to hold the result
shell << Table(i, List(i, 1, 10)); // In Mathematica Table[i, {i, 1, 10}]
shell >> result_list;
std::cout << result_list << std::endl; // Prints List[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
std::cout << result_list->stringify() << std::endl; // Prints List[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
std::vector<int> list;
list = cast<std::vector<int>>(result_list);

shell.import("/path/to/package.m") can be used to import a mathematica package.

shell << Import("/path/to/package.m")` 

also yields the same as well. Because Import is also a mathametica function that can be declared using MATHEMATICA_DECLARE

I have tested it only on Linux and Mac platforms, but it should work on windows also. The Project is in Free BSD License.

mathematica++ gitlab repository | website | wiki

$\endgroup$
  • $\begingroup$ "However function names are mostly similar." They are not mostly similar, they are exactly the same. $\endgroup$ – Szabolcs Sep 2 '18 at 13:45
  • $\begingroup$ Yes. I guessed this. But I didn't find any supporting link that confirms this. So I played safe. Thanks for confirming. $\endgroup$ – Neel Basu Sep 2 '18 at 13:46
  • $\begingroup$ "Mathematica is now replacing MathLink with WSTP." I know that's what they say, but that's not what they do. LibraryLink still requires using the mathlink.h header. This is probably because the kernel itself uses the ML functions internally (this is visible when opening the executable with a hex editor), and LibraryLink libraries run in the kernel process. It's a shame that even the LibraryLink documentation shows WS stuff which doesn't even work. It's ridiculous. $\endgroup$ – Szabolcs Sep 2 '18 at 13:47

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.