26
$\begingroup$

Is it possible to create a C++ program using MathLink that will invoke the Maple kernel and execute a very basic Maple command using OpenMaple?

I'm envisioning the following:

Install["MapleLink"]

starts the external program MapleLink and installs the Mathematica definition RunMaple.

?RunMaple

RunMaple[expr] returns a string which is the output when Maple executes expression expr

A sample output:

RunMaple["seq(i, i=0..3);"]

"0, 1, 2, 3"

I'm also open to using J/Link.

$\endgroup$
8
  • 2
    $\begingroup$ Should be quite possible, but I would rather use Java bindings. Cross-platform, higher-level, also JLink is much easier to use than MathLink - what's not to like? $\endgroup$ Commented Oct 9, 2012 at 13:45
  • $\begingroup$ I'm totally open to any solution. I'll edit the problem to reflect this. $\endgroup$ Commented Oct 9, 2012 at 13:50
  • 2
    $\begingroup$ out of curiosity what is your usage/application. (Why are you unable to just run the Maple code in Maple?) $\endgroup$ Commented Oct 9, 2012 at 21:33
  • $\begingroup$ I would find it convenient to access the output from some commands in the RegularChains package. $\endgroup$ Commented Oct 10, 2012 at 0:20
  • $\begingroup$ Did you find a solution to this James? I am interested in using a few Maple functions inside Mathematica too. $\endgroup$
    – Szabolcs
    Commented Jan 23, 2013 at 2:10

2 Answers 2

21
$\begingroup$

Begin Note: I have successfully got this working in the following environments.

  1. On a Mac PC running version 9.0.0.0 using a locally installed JRE (version 1.6.0_37).
  2. On a Windows PC running version 9.0.0.0 using a locally installed JRE (version 1.7.0_13).

I found that on my Windows PC, the JRE included with Mathematica is version 1.6.0_10 and the method described below fails when initializing the Maple engine at this step:

MapleEngine = JavaNew[engineload, {"java"}, defaultexception, Null, Null]
Java::excptn: "A Java exception occurred: "java.lang.UnsatisfiedLinkError: "

So if you are getting the error seen above, try loading a newer version of Java when doing ReinstallJava. I show how to do this below.

You can find out the version of Java that Mathematica is running by executing the following.

Needs["JLink`"]
ReinstallJava[];
LoadJavaClass["java.lang.System"];
java`lang`System`getProperty["java.version"]

End Note

Java OpenMaple provides an interface between the Maple evaluation engine and a Java program. J/Link provides Mathematica users with the ability to interact with arbitrary Java classes directly from the front end. The goal here is to use J/Link to access the methods from OpenMaple. It is assumed that Maple is installed on the computer you are doing this on.

First, load J/Link.

Needs["JLink`"]

We will refer to the location of the Maple installation as MAPLEDIR and the location of the Java OpenMaple native library as BINDIR as per this example. You can find these locations by executing, kernelopts(mapledir); and kernelopts(bindir); in Maple, respectively. The images below show the outputs in Windows and OS X, respectively.

kernelopts(mapledir) and kernelopts(bindir) in Maple in Windows

kernelopts(mapledir) and kernelopts(bindir) in Maple in OS X

Here are the directories from my Windows and Mac machine, respectively.

(* Windows *)
MAPLEDIR = "C:\\Program Files (x86)\\Maple 16";
BINDIR = "C:\\Program Files (x86)\\Maple 16\\bin.win";
(* OS X *)
MAPLEDIR = "/Library/Frameworks/Maple.framework/Versions/16";
BINDIR = "/Library/Frameworks/Maple.framework/Versions/16/bin.APPLE_UNIVERSAL_OSX";

Add the Java OpenMaple components to the class path.

(* Windows *)
AddToClassPath[MAPLEDIR <> "\\java\\externalcall.jar"];
AddToClassPath[MAPLEDIR <> "\\java\\jopenmaple.jar"];
(* OS X *)
AddToClassPath[MAPLEDIR <> "/java/externalcall.jar"];
AddToClassPath[MAPLEDIR <> "/java/jopenmaple.jar"];

Update the environment variables.

(* Windows *)
oldPATH = "PATH" /. GetEnvironment["PATH"];
SetEnvironment["PATH" -> oldPATH <> ";" <> BINDIR];
(* OS X *)
SetEnvironment["DYLD_LIBRARY_PATH" -> BINDIR];
SetEnvironment["MAPLE" -> MAPLEDIR];

Since SetEnvironment is new in 9, lower versions should see this answer.

Now that we are done with the set up, we will launch the Java runtime. As per the Note above, I launch the local version of Java in Windows and use the built-in version of Java in OS X.

(* Windows *)
ReinstallJava[CommandLine -> "C:\\Program Files (x86)\\Java\\jre7\\bin\\java.exe"]
(* OS X *)
ReinstallJava[];

Next, create a default instance of a class implementing the EngineCallBacks interface.

exceptionload = LoadJavaClass["com.maplesoft.openmaple.EngineCallBacksDefault"]
defaultexception = JavaNew[exceptionload]
JavaClass[com.maplesoft.openmaple.EngineCallBacksDefault, <>]
« JavaObject[com.maplesoft.openmaple.EngineCallBacksDefault] »

Next, create an instance of Engine to start the Maple session. Only one Engine can be created during a single run of the JVM, even after the Engine has been stopped.

engineload = LoadJavaClass["com.maplesoft.openmaple.Engine"]
MapleEngine = JavaNew[engineload, {"java"}, defaultexception, Null, Null]
JavaClass[com.maplesoft.openmaple.Engine, <>]
« JavaObject[com.maplesoft.openmaple.Engine] »

In Windows, if the Maple kernel gets initialized, then the following splash screen briefly appears. (This did not show up in OS X.)

Maple splash screen in Windows

Using MapleEngine, you can now perform computations using evaluate. Depending on what the input is, the object returned by evaluate differs.

out = MapleEngine@evaluate["seq(i, i=0..3);"];
« JavaObject[com.maplesoft.openmaple.Expseq] »

In this example, the method returns an Expseq object. However, Algebraic is the base class for every Java OpenMaple class that represents a Maple object. Since Expseq publicly inherits from Algebraic, we can use methods from Algebraic to study it. First, we load the Algebraic class.

algebraicload = LoadJavaClass["com.maplesoft.openmaple.Algebraic"]
JavaClass[com.maplesoft.openmaple.Algebraic, <>]

Now we can manipulate our output out.

out@algebraicload`toString[]
[0, 1, 2, 3]

Here, out has head String.

You can create persisting variables using the newName method. We assign the value 100 to the variable abcde and then add 5 to it.

name = MapleEngine@newName["abcde", True];
name@assign[MapleEngine@newNumeric[100]];
out = MapleEngine@evaluate["abcde + 5;"];
out@algebraicload`intValue[]
105

There is a lot more you can do if you take a look at the Java OpenMaple API. The code above is only a starting point. I can imagine someone building a nice package off of this.

$\endgroup$
6
  • $\begingroup$ Excellent! If you make a small package out of this, could you please put it on GitHub for easier collaboration? $\endgroup$
    – Szabolcs
    Commented Jan 26, 2013 at 2:05
  • $\begingroup$ I definitely will. $\endgroup$ Commented Jan 26, 2013 at 19:31
  • $\begingroup$ I think Mathematica doesn't include Java on OS X so we're free to install whichever version we'd like to use. (It does indeed include 1.6u10 on Windows). Thanks for the hints on getting it working on Win! $\endgroup$
    – Szabolcs
    Commented Feb 8, 2013 at 4:53
  • $\begingroup$ What I'm actually interested in is transferring large integers (larger than machine integers). Actually transferring a list of them. Is the best way just using a string? $\endgroup$
    – Szabolcs
    Commented Feb 8, 2013 at 4:56
  • $\begingroup$ Oh, I did not know it did not include it. I will make that change. In regards to the large integers, I think a string may be your best bet. A quick search on "max length of Java strings" brings up a result saying strings can be no longer than Integer.MAX_VALUE (in excess of two billion) characters. OpenMaple supports strings via MString: maplesoft.com/support/help/Maple/view.aspx?path=OpenMaple/Java/… $\endgroup$ Commented Feb 8, 2013 at 5:28
5
$\begingroup$

I have upvoted both the question and the excellent answer by James Rohal. In his answer James mentioned only Windows and macOS, but when I tried to run this code on Linux, it did not work out of the box. It took me a while to figure out what was the problem. Apart from the obvious replacement DYLD_LIBRARY_PATH -> LD_LIBRARY_PATH I also had to specify the CLASSPATH two times: when executing ReinstallJava and as a separate environmental variable. Here I would like to provide my working Linux code for the benefit of other Linux users. Since Linux was not mentioned in the original answer by James, I hope that this is fine.

The following has been tested with Fedora 28 (64-bit), Mathematica 11.3 and Maple 2015. My Maple distribution is located in /media/Data/Software/maple2015. The Java version is 1.8.0_172 from Oracle.

<< JLink`

MAPLEDIR = "/media/Data/Software/maple2015";
BINDIR = FileNameJoin[{MAPLEDIR, "bin.X86_64_LINUX"}];
CLASSDIR = FileNameJoin[{MAPLEDIR, "java"}];

SetEnvironment["MAPLE" -> MAPLEDIR];
SetEnvironment["LD_LIBRARY_PATH" -> BINDIR];
SetEnvironment["CLASSPATH" -> FileNameJoin[{CLASSDIR, "*"}]];

ReinstallJava[CommandLine -> "/usr/bin/java", ClassPath -> CLASSDIR]

exceptionload = 
 LoadJavaClass["com.maplesoft.openmaple.EngineCallBacksDefault"]
defaultexception = JavaNew[exceptionload]
engineload = LoadJavaClass["com.maplesoft.openmaple.Engine"]

MapleEngine = 
 JavaNew[engineload, {"java"}, defaultexception, Null, Null]

out = MapleEngine@evaluate["seq(i, i=0..3);"];

algebraicload = LoadJavaClass["com.maplesoft.openmaple.Algebraic"]

out@algebraicload`toString[]

enter image description here

$\endgroup$
2
  • $\begingroup$ I have problems in using this. When running the command: MapleEngine = JavaNew[engineload, {"java"}, defaultexception, Null, Null] I encountered an error: JavaNew::fail: Error calling constructor for class com.maplesoft.openmaple.Engine. Do you know why? $\endgroup$
    – Light man
    Commented Apr 21, 2021 at 19:12
  • $\begingroup$ There was a "]; missing in MapleEngine@evaluate (it is correct in the screenshot, though), but apart from that everything works for me with Mma 12.1 and Maple 2020. $\endgroup$
    – vsht
    Commented Apr 23, 2021 at 14:14

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