【问题标题】:How to call java objects and functions from CPython?如何从 CPython 调用 java 对象和函数?
【发布时间】:2010-10-01 02:47:17
【问题描述】:

我有一个 python 程序,它在 CPython 实现上运行,在其中我必须调用一个在 java 程序中定义的函数。我该怎么做?

如果也能使用一些 java 对象就好了。

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

【问题讨论】:

    标签: java python function language-interoperability


    【解决方案1】:

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

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

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

    如果您不关心性能。

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

      【解决方案3】:

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

      【讨论】:

      • python-javabridge 与jpype 相比如何?性能/稳定性?
      【解决方案4】:

      很抱歉恢复线程,但我想我有一个更好的答案:-)

      您还可以使用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 的作者

      【讨论】:

      • 使用套接字有什么好处?不是比JNI慢吗?你有性能统计数据吗?
      • JNI 的开销肯定更少!套接字更便携(JNI 在 Windows 上并不总是很有趣)并且支持更多的场景(例如,Python 解释器在与 JVM 不同的机器上)。
      【解决方案5】:

      最简单的方法是

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

        public class ExposeAMethod {
            public static void main( String args[] ) {
                 TheClassToExpose  x = new TheClassToExpose();
                x.theFunction();
            }
        }
        
      2. 编译并构建一个可执行的 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 程序。

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-03
          • 1970-01-01
          • 2017-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多