7

I use Wolfram Workbench 2.0. I can get a KernelLink object and evaluate some simple expressions like "2+2". But I don't know how to export a package and execute any functions from Java code. Please, show me any example.

Verbeia
  • 34,233
  • 9
  • 109
  • 224
Daniil
  • 73
  • 1
  • 4
  • 1
    I'm not sure I understand the question, but according to the documentation, J/Link and specifically KernelLink are for calling Java from Mathematica, not the other way around. Do you mean execute any functions that are written in Java, that you want to use in Mathematica? – Verbeia Jun 03 '12 at 11:22
  • 3
    @Verbeia No, JLink works both ways. There is an additional tutorial on this part of JLink, here – Leonid Shifrin Jun 03 '12 at 14:26
  • I am writing a program in java, which is a function of my Wolfram package. I want to connect the package and call the desired function. I think this is done with ml.evaluate ("<< MyPackage.m"); But I could not get my program to work. Please tell me how to run the desired function in a package of java with example? – Daniil Jun 05 '12 at 10:09

1 Answers1

11

Preamble

In fact, the relevant example can be found in the documentation, here, in the "Sample program" section. To make this useful also for folks who don't have experience with Java development in WorkBench, I will illustrate how this can be done from within Mathematica, by using the interactive Java reloader from this post. You will have to figure out how to run this from within WorkBench, but this should not be really hard.

Illustration from within Mathematica

Sample code

I will construct a sample class which loads the CompiledFunctionTools` package and prints to the Java console the result of CompilePrint function applied to some sample Compile-d function, such as e.g. Compile[{x}, x + Sin[x]]. This is pretty much an adaptation of the example from JLink Help, linked above.

samplecode = 
"
 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(&quot;Fatal error opening link: &quot; + e.getMessage()); return; } try { // Get rid of the initial InputNamePacket the kernel will send // when it is launched. ml.discardAnswer();

    ml.evaluate(\&quot;Needs[\\\&quot;CompiledFunctionTools`\\\&quot;]\&quot;);
    ml.discardAnswer();

    String strResult = 
                ml.evaluateToOutputForm(
                   \&quot;CompilePrint[Compile[{x},x+Sin[x]]]\&quot;, 0);
    System.out.println(
                   \&quot;Instructions for function Compile[{x},x+Sin[x]]: \&quot; 
                        + strResult);

            ml.putFunction(\&quot;EvaluatePacket\&quot;, 1);
    ml.putFunction(\&quot;CompilePrint\&quot;, 1);
        ml.putFunction(\&quot;Compile\&quot;,2);
        ml.putFunction(\&quot;List\&quot;,1);
                ml.putSymbol(\&quot;x\&quot;);
        ml.putFunction(\&quot;Plus\&quot;,2);
            ml.putSymbol(\&quot;x\&quot;);
            ml.putFunction(\&quot;Sin\&quot;,1);
                ml.putSymbol(\&quot;x\&quot;);        
    ml.endPacket();
    ml.waitForAnswer();
    strResult = ml.getString();
    System.out.println(
               \&quot;Now conbining function call from pieces: \&quot; + strResult);  

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

} }";

Load Java reloader

Now, you have to either copy and paste the code for the Java reloader from the link above, and run it in Front-End, or put that code in a package, place it where Mathematica can find it (e.g. FileNameJoin[{$UserBaseDirectory,"Applications"}], and call Needs["SimpleJavaReloader`"].

Using Java reloader

First, we will have to add the jlink.jar to Java classpath for Java compiler. Here is the standard location of it:

jlinkpath =  FileNameJoin[{$InstallationDirectory, "SystemFiles", "Links", 
    "JLink", "JLink.jar"}]

Let us check that the files exists:

FileExistsQ[jlinkpath]
True

We are now ready to compile it:

JCompileLoad[samplecode,{jlinkpath}]
 JavaClass[SampleProgram,<>]

The class has been (hopefully) compiled and loaded by now. To see the output it produces, we can enable the Java console:

ShowJavaConsole[]

Now we make a call:

SampleProgram`main[{"-linkmode", "launch", "-linkname", 
      "c:\\program files\\wolfram research\\mathematica\\8.0\\mathkernel.exe"}]

You will have to adjust the path to the mathkernel executable for your machine (I assume you are on Windows. For other platforms, the mentioned section of JLink Help lists the right commands to launch the kernel).

We now call the Java console again:

ShowJavaConsole[]

Here is the screenshot of the Java console on my machine after that:

enter image description here

WorkBench

While I did not try using WorkBench with this, this should be even simpler:

  • Create a Java project in WB
  • Create a source file for your class
  • Add jlink.jar to the set of libraries used in the project (I assume you know how to do that)
  • You will have to run the math kernel from the Java process, perhaps by calling the Process class, or by any other means.
Leonid Shifrin
  • 114,335
  • 15
  • 329
  • 420
  • Thank you for the informative answer. This is an interesting way to solve the problem. But my question is not really the point. I am writing a program in java, which is a function of my Wolfram package. I want to connect the package and call the desired function. I think this is done with ml.evaluate ("<< MyPackage.m"); But I could not get my program to work. Please tell me how to run the desired function in a package of java with example? – Daniil Jun 05 '12 at 10:06
  • @Daniil You probably did not get the point of my answer, perhaps I should have explained it differently. What I present is a Java program - the class SampleProgram. I just decided to compile and run the class from Mathematica to make a presentation celf-contained for folks who don't use IDEs. What you have to do it to take this class, create in in your Java project in WorkBench (WB), add jlink.jar to your classpath, and figure out the right way to launch Mathematica kernel from WB, which is something like ... – Leonid Shifrin Jun 05 '12 at 10:55
  • @Daniil ... "java -classpath .;....\JLink.jar SampleProgram -linkmode launch -linkname "c:\program files\wolfram research\mathematica\8.0\mathkernel.exe" - you can launch the kernel from WB as well, or even from Java, by uding the Process class or plain System calls. The class loads a package (CompiledFunctionTools`), and uses the CompilePrint function from that package, to display instructions generated by Compile for a sample compiled function - this is just an example. So, just take this class verbatim and use it from Java side. – Leonid Shifrin Jun 05 '12 at 10:58
  • @Daniil If this is still unclear, I will expand my answer with further explanations when I have time. – Leonid Shifrin Jun 05 '12 at 11:00
  • I understand your answer. You are using CompiledFunctionTools `to compile functions. It has nothing to do with the packages where I want to run the function. I have a package myFunctions.m and I want to perform the function of it. This is done using JLink something like this: – Daniil Jun 05 '12 at 11:36
  • `...

    ml = MathLinkFactory.createKernelLink (mlArgs); ml.discardAnswer (); ml.evaluate ("<< " myPackage.m \ ""); ml.discardAnswer (); ml.evaluate ("myFunction [myArgs]"); ml.waitForAnswer (); Expr result = ml.getExpr (); System.out.println (result); ...`

    – Daniil Jun 05 '12 at 11:36
  • You offer to compile all of the features found in Java by writing them as a String. I'd like to just call them from java and get an answer. Thank you for your way, but it's not quite what I need. PS: I understand perfectly how I should compile and run the project. It's not a problem for me. Thank you for your attention to my problem – Daniil Jun 05 '12 at 11:37
  • @Daniil "I have a package myFunctions.m and I want to perform the function of it." Yes, this is exactly what I was showing. CompilePrint is just an example function from a package CompiledFunctionTools`. I could pick some function f from a package myPackage` just as well. "You offer to compile all of the features found in Java by writing them as a String" - no, this was just for an illustration. You can pick this class's code from above, and just create it in the WB, as you normally do (copy-paste there). You won't need the rest of the Mathematica code I was showing, then. – Leonid Shifrin Jun 05 '12 at 12:00
  • @Daniil I understand that the way I put my answer can be confusing. I will expand it with specific steps on how to do the same thing from within WB/Java, when I get some free time. – Leonid Shifrin Jun 05 '12 at 12:02
  • I apologize. I do not understand your first answer. You described it right. I thought that you propose to use the package CompiledFunctionTools ` to create functions from java code. Thanks for your help, I really figured out. – Daniil Jun 05 '12 at 19:57
  • @Daniil Ok, great. Most people here go from the Mathematica side, and I tried to make the answer also understandable for them. I certainly could have made it more clear though. Thanks for the accept. – Leonid Shifrin Jun 05 '12 at 20:06
  • Will MathKernel supplied with CDF Player to work with my packages? My code works for MathKernel of Wolfram Mathematica 8.0, but not work with MathKernel of the CDF Player. I execute myPackage.m. What reason could be in this problem? May be you now any differences between Wolfram Mathematica 8.0 MathKernel and CDF Player MathKernel? – Daniil Jun 05 '12 at 21:38
  • 2
    @Daniil I strongly suspect that the answer is no - chances are that you won't be able to use CDF with Java. What you might be able to do is to create CDF on the fly from Java, and embed in a web page if you have a server and want to send it to the client. I suggest you read this discussion. Generally, it seems that the best way to think about CDF is that it is similar to PDF, but more interactive: it is a format to share information, but not a deployment channel, at least not directly. – Leonid Shifrin Jun 05 '12 at 21:44