Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call java objects and functions from CPython?

I have a python program, which runs on the CPython implementation, and inside it I must call a function defined in a java program. How can I do this?

It would be nice to be able to use some java objects too.

Jython is not an option. I must run the python part in CPython.

like image 749
nosklo Avatar asked Jan 13 '09 10:01

nosklo


4 Answers

Apologies for resurrecting the thread, but I think I have a better answer :-)

You could also use Py4J which has two parts: a library that runs in CPython (or any Python interpreter for that matter) and a library that runs on the Java VM you want to call.

There is an example on the frontpage and lots of documentation, but essentially, you just call Java methods from your python code as if they were python methods:

>>> from py4j.java_gateway import JavaGateway
>>> gateway = JavaGateway()                        # connect to the JVM
>>> java_object = gateway.jvm.mypackage.MyClass()  # invoke constructor
>>> other_object = java_object.doThat()
>>> other_object.doThis(1,'abc')
>>> gateway.jvm.java.lang.System.out.println('Hello World!') # call a static method

The communication is done through sockets instead of JNI.

Disclaimer: I am the author of Py4J

like image 85
Barthelemy Avatar answered Nov 17 '22 16:11

Barthelemy


The easiest thing to do is

  1. Write a trivial CLI for your java "function". (There's no such thing, so I'll assume you actually mean a method function of a Java class.)

    public class ExposeAMethod {
        public static void main( String args[] ) {
             TheClassToExpose  x = new TheClassToExpose();
            x.theFunction();
        }
    }
    
  2. Compile and build an executable JAR file with this as the entry point. Call it ExposeAMethod.jar

  3. Call this from a command created by subprocess.

    import subprocess
    p = subprocess.Popen("java -jar ExposeAMethod.jar", shell=True)
    sts = os.waitpid(p.pid, 0)
    

This is the minimum. And it's really not much. I count 6 lines of java, 3 lines of Python and you're up and running.

If you want to pass arguments to this Java class constructor or method function, you'll have to write a few more lines of code. You have two choices.

  • Read the arguments from stdin, write the results on stdout. This is relatively easy and performs really well.

  • Parse the arguments as command-line options to Java, write the results on stdout. This is slightly harder, but generalizes very nicely. The bonus is that you now have a useful command-line Java program that you can reuse.

like image 40
S.Lott Avatar answered Nov 17 '22 15:11

S.Lott


You'll have to create a python C extension that embeds Java - based on something like http://www.javaworld.com/javaworld/jw-05-2001/jw-0511-legacy.html or else you'll have to start java in a separate subprocess.

like image 1
Douglas Leeder Avatar answered Nov 17 '22 14:11

Douglas Leeder


If you don't want to go the write your own JNI/C route.

The other option is to use jpype which for me is always what I use to access Oracle databases becuase installing the oracle c drivers on a PC is a pita. You can do stuff like (from docs):

 from jpype import * 
 startJVM("d:/tools/j2sdk/jre/bin/client/jvm.dll", "-ea") # or path to your jvm
 java.lang.System.out.println("hello world") 
 shutdownJVM()

It hasn't been updated in a while and there isn't much in the way of documentation but it does work reasonably well.

  • homepage
  • docs
like image 7
Ravi Avatar answered Nov 17 '22 15:11

Ravi