我有一个 python 程序,它在 CPython 实现上运行,在它里面我必须调用一个在 java 程序中定义的函数。我怎样才能做到这一点?
能够使用一些java对象也很好。
Jython 不是一种选择。我必须在 CPython 中运行 python 部分。
我有一个 python 程序,它在 CPython 实现上运行,在它里面我必须调用一个在 java 程序中定义的函数。我怎样才能做到这一点?
能够使用一些java对象也很好。
Jython 不是一种选择。我必须在 CPython 中运行 python 部分。
为恢复线程道歉,但我认为我有一个更好的答案:-)
您还可以使用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 的作者
最简单的做法是
为您的 java“函数”编写一个简单的 CLI。(没有这样的东西,所以我假设您实际上是指 Java 类的方法函数。)
public class ExposeAMethod {
public static void main( String args[] ) {
TheClassToExpose x = new TheClassToExpose();
x.theFunction();
}
}
以 this 作为入口点编译并构建一个可执行的 JAR 文件。称它为
ExposeAMethod.jar
从子进程创建的命令中调用它。
import subprocess
p = subprocess.Popen("java -jar ExposeAMethod.jar", shell=True)
sts = os.waitpid(p.pid, 0)
这是最低限度。而且真的不多。我数了 6 行 java,3 行 Python,你就开始运行了。
如果您想将参数传递给这个 Java 类的构造函数或方法函数,则必须再编写几行代码。你有两个选择。
从标准输入读取参数,将结果写入标准输出。这相对容易并且性能非常好。
将参数解析为 Java 的命令行选项,将结果写入标准输出。这稍微难一些,但可以很好地概括。好处是您现在拥有一个可以重用的有用的命令行 Java 程序。
如果您不想编写自己的 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()
它已经有一段时间没有更新了,文档的方式也不多,但它确实工作得很好。
我不知道 Python,但上次我不得不从 C 应用程序(NT 服务)调用 java,我必须加载jvm.dll
. 查看 JNI 文档。
另外,你打电话总是打电话
os.system("java com.myapp.MyClass")
如果您不关心性能。
您必须创建一个嵌入 Java 的 python C 扩展 - 基于http://www.javaworld.com/javaworld/jw-05-2001/jw-0511-legacy.html之类的东西,否则您将不得不在单独的子进程中启动 java。
查看我们的项目python-javabridge。它是一个围绕 JNI 的 Python 包装器,被CellProfiler大量使用。它提供对 JNI 的低级访问和对 Java 对象的基于反射的高级访问。