如何从 CPython 调用 java 对象和函数?

发布于 2024-07-11 12:48:20 字数 166 浏览 10 评论 0原文

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

如果能够使用一些 java 对象那就太好了。

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

允世 2024-07-18 12:48:20

最简单的事情是

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

    公共类ExposeAMethod { 
          公共静态无效主(字符串参数[]){ 
               TheClassToExpose x = new TheClassToExpose(); 
              x.theFunction(); 
          } 
      } 
      
  2. 以此为入口点编译并构建一个可执行 JAR 文件。 叫它
    ExposeAMethod.jar

  3. 从子进程创建的命令中调用此函数。

    导入子流程 
      p = subprocess.Popen("java -jar ExposeAMethod.jar", shell=True) 
      sts = os.waitpid(p.pid, 0) 
      

这是最小值。 而且确实不多。 我数了数 6 行 java,3 行 Python,你就可以启动并运行了。

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

  • 从 stdin 读取参数,将结果写入 stdout。 这相对简单并且性能非常好。

  • 将参数解析为 Java 的命令行选项,并将结果写入 stdout。 这稍微困难一些,但概括起来非常好。 额外的好处是,您现在拥有一个可以重用的有用的命令行 Java 程序。

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.

诺曦 2024-07-18 12:48:20

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

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

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

幸福还没到 2024-07-18 12:48:20

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

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.

眼波传意 2024-07-18 12:48:20

如果您不想编写自己的 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()

它已经有一段时间没有更新了,并且文档中没有太多内容,但它确实工作得相当好。

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.

心病无药医 2024-07-18 12:48:20

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

始终会调用。

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

另外,如果您不关心性能,则

I don't know for Python, but last time I had to call java from C application (NT service) I had to load jvm.dll. Take a look at JNI documentation.

Also, you call always call

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

if you are not concerned about performance.

迷鸟归林 2024-07-18 12:48:20

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

Look at our project python-javabridge. It's a Python wrapper around the JNI, heavily used by CellProfiler. It offers both low-level access to the JNI and a high-level reflection-based access to Java objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文