11

我有一个 python 程序,它在 CPython 实现上运行,在它里面我必须调用一个在 java 程序中定义的函数。我怎样才能做到这一点?

能够使用一些java对象也很好。

Jython 不是一种选择。我必须在 CPython 中运行 python 部分。

4

6 回答 6

15

为恢复线程道歉,但我认为我有一个更好的答案:-)

您还可以使用Py4J,它有两个部分:一个在 CPython(或任何 Python 解释器)中运行的库和一个在您要调用的 Java VM 上运行的库。

头版上有一个示例和大量文档,但本质上,您只需从 Python 代码中调用 Java 方法,就好像它们是 Python 方法一样:

>>> 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

通信是通过套接字而不是 JNI 完成的。

免责声明:我是 Py4J 的作者

于 2010-09-25T10:55:08.823 回答
9

最简单的做法是

  1. 为您的 java“函数”编写一个简单的 CLI。(没有这样的东西,所以我假设您实际上是指 Java 类的方法函数。)

    public class ExposeAMethod {
        public static void main( String args[] ) {
             TheClassToExpose  x = new TheClassToExpose();
            x.theFunction();
        }
    }
    
  2. 以 this 作为入口点编译并构建一个可执行的 JAR 文件。称它为 ExposeAMethod.jar

  3. 从子进程创建的命令中调用它。

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

这是最低限度。而且真的不多。我数了 6 行 java,3 行 Python,你就开始运行了。

如果您想将参数传递给这个 Java 类的构造函数或方法函数,则必须再编写几行代码。你有两个选择。

  • 从标准输入读取参数,将结果写入标准输出。这相对容易并且性能非常好。

  • 将参数解析为 Java 的命令行选项,将结果写入标准输出。这稍微难一些,但可以很好地概括。好处是您现在拥有一个可以重用的有用的命令行 Java 程序。

于 2009-01-13T11:28:40.320 回答
7

如果您不想编写自己的 JNI/C 路线。

另一种选择是使用 jpype,对我来说,它始终是我用来访问 Oracle 数据库的工具,因为在 PC 上安装 oracle c 驱动程序是一个皮塔饼。您可以执行以下操作(来自文档):

 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()

它已经有一段时间没有更新了,文档的方式也不多,但它确实工作得很好。

于 2009-01-14T20:00:08.073 回答
1

我不知道 Python,但上次我不得不从 C 应用程序(NT 服务)调用 java,我必须加载jvm.dll. 查看 JNI 文档。

另外,你打电话总是打电话

os.system("java com.myapp.MyClass") 

如果您不关心性能。

于 2009-01-13T11:11:40.883 回答
1

您必须创建一个嵌入 Java 的 python C 扩展 - 基于http://www.javaworld.com/javaworld/jw-05-2001/jw-0511-legacy.html之类的东西,否则您将不得不在单独的子进程中启动 java。

于 2009-01-13T11:15:46.947 回答
1

查看我们的项目python-javabridge。它是一个围绕 JNI 的 Python 包装器,被CellProfiler大量使用。它提供对 JNI 的低级访问和对 Java 对象的基于反射的高级访问。

于 2014-06-16T16:07:00.083 回答