如何从perl6调用Java方法

问题描述 投票:8回答:3
use java::util::zip::CRC32:from<java>;

my $crc = CRC32.new();
for 'Hello, Java'.encode('utf-8') {
    $crc.'method/update/(B)V'($_);
}
say $crc.getValue();

遗憾的是,这不起作用

Method 'method/update/(B)V' not found for invocant of class 'java.util.zip.CRC32'

此代码可从以下链接获得。这是我能找到的唯一例子

  1. Rakudo Perl 6 on the JVM (slides)
  2. Perl 6 Advent Calendar: Day 03 – Rakudo Perl 6 on the JVM
jvm jvm-languages perl6 java-interop rakudo
3个回答
7
投票

Final answer

结合下面的你的答案清理部分中解释的代码清理与Pepe Schwarz在下面的期望警报部分中提到的改进,我们得到:

use java::util::zip::CRC32:from<Java>;

my $crc = CRC32.new();

for 'Hello, Java'.encode('utf-8').list { 
    $crc.update($_);
}

say $crc.getValue();

Your answer cleaned up

use v6;
use java::util::zip::CRC32:from<Java>;

my $crc = CRC32.new();

for 'Hello, Java'.encode('utf-8').list { # Appended `.list` 
    $crc.'method/update/(I)V'($_); 
}
say $crc.getValue();

一个重要的改变位是附加的.list

'Hello, Java'.encode('utf-8')片段返回一个对象,一个utf8。该对象只返回一个值(本身)到q​​azxswpoi语句。所以for只迭代一次,将对象传递给代码块,其中包含for线。

如果update行是update,那么迭代一次就有意义了,.'method/update/([B)V'映射到需要8位整数缓冲区的Java方法,这基本上就是Perl 6 utf8。然而,这将需要一些支持Perl 6代码(可能在核心编译器中)将Perl 6 utf8编组(自动转换)为Java buf[],如果该代码曾经存在/工作,那么当我使用最新的Rakudo。

但如果一个人如上所示附加一个明智的.list并更改代码块以匹配,那么事情就会成功。

首先,.list导致for语句迭代一系列整数。

其次,和你一样,我调用了Java方法的整数arg版本(.'method/update/(I)V')而不是原始的缓冲区arg版本,然后代码正常工作。 (这意味着从Perl 6 utf8对象返回的无符号8位整数的二进制表示已经完全是Java方法所期望的,或者是为您自动编组的。)

另一个必要的变化是from<java>需要在下面的评论中使用from<Java> - 谢谢。

Expectation alert

截至2015年1月:

  • 仅仅使用Rakudo / NQP的JVM后端(即在JVM上运行纯P6代码)仍需要更多强化才能正式宣布准备用于生产。 (这是整个P6生态系统预计将在今年进行的全面强化的补充。)JVM后端有望在2015年实现 - 它有望成为Perl 6首次正式发布的一部分今年的生产使用 - 但这在很大程度上取决于需求,并且有更多的开发人员使用它并提供补丁。
  • 调用Java代码的P6代码是一个额外的项目。 Pepe Schwarz在过去几个月里取得了很大的进步,他们正在加快速度,学习代码库和landing commits。他已经实现了在本答案开头显示的明显更好的短名称调用,并完成了更多用于在P6和Java类型之间进行转换的编组逻辑,并且正在积极征求反馈和特定改进请求。

2
投票

负责Java互操作的这个区域的代码可以在类org.perl6.nqp.runtime.BootJavaInterop中找到。它表明重载方法由字符串method/<name>/<descriptor>标识。描述符在函数org.objectweb.asm.Type#getMethodDescriptor中计算。这个罐子可以通过http://mvnrepository.com/artifact/asm/asm的maven获得。

import java.util.zip.CRC32
import org.objectweb.asm.Type

object MethodSignatures {
  def printSignature(cls: Class[_], method: String, params: Class[_]): Unit = {
    val m = cls.getMethod(method, params)
    val d = Type.getMethodDescriptor(m)
    println(m)
    println(s"\t$d")
  }
  def main(args: Array[String]) {
    val cls = classOf[CRC32]

    # see https://docs.oracle.com/javase/8/docs/api/java/util/zip/CRC32.html
    val ab = classOf[Array[Byte]]
    val i = classOf[Int]

    printSignature(cls, "update", ab)
    printSignature(cls, "update", i)
  }
}

这打印

public void java.util.zip.CRC32.update(byte[])
    ([B)V
public void java.util.zip.CRC32.update(int)
    (I)V

因为我想调用这个重载方法的update(int)变体,所以正确的方法调用(在示例程序的第5行)是

$crc.'method/update/(I)V'($_);

这与崩溃

This representation can not unbox to a native int

最后,由于某种原因,我不明白,改变相同的行

$crc.'method/update/(I)V'($_.Int);

修复,示例运行正常。

代码的最终版本是

use v6;
use java::util::zip::CRC32:from<java>;

my $crc = CRC32.new();

for 'Hello, Java'.encode('utf-8') {
    $crc.'method/update/(I)V'($_.Int);
}
say $crc.getValue();

1
投票

我在Perl 6.c上进行了以下修改(2018年1月4日):

use v6;
use java::util::zip::CRC32:from<JavaRuntime>;

my $crc = CRC32.new();

for 'Hello, Java'.encode('utf-8').list { 
    $crc.update($_);
}
say $crc.getValue();

导致:

% perl6-j --version
This is Rakudo version 2017.12-79-g6f36b02 built on JVM
implementing Perl 6.c.

% perl6-j crcjava.p6 
1072431491
© www.soinside.com 2019 - 2024. All rights reserved.