10
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. JVM 上的 Rakudo Perl 6(幻灯片)
  2. Perl 6 出现日历:第 3 天 – Rakudo Perl 6 在 JVM
4

3 回答 3

9

最终答案

将下面您的答案清理部分中解释的代码清理与下面的期望警报部分中提到的 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();

您的答案已清理

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')片段返回一个对象 a utf8for该对象仅向语句返回一个值(本身) 。所以for只迭代一次,将对象传递给包含update行的代码块。

update如果该行是迭代一次可能是有意义的.'method/update/([B)V',它映射到一个 Java 方法,该方法需要一个 8 位整数的缓冲区,这本质上是 Perl 6utf8的内容。但是,这需要一些支持 Perl 6 的代码(大概在核心编译器中)才能将 Perl 6 编组(自动转换)utf8成 Java buf[],如果该代码曾经存在/工作过,那么当我使用最新的 Rakudo 进行测试时,它肯定不起作用.

.list但是,如果如上所示添加一个明智的并更改代码块以匹配,事情就会解决。

首先,语句中迭代一系列整数的.list结果。for

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

另一个需要的更改是from<java>需要from<Java>根据您在下面的评论 - 谢谢。

预期警报

截至 2015 年 1 月:

  • 仅仅为 Rakudo/NQP 使用 JVM 后端(即在 JVM 上运行纯 P6 代码)仍然需要更多的强化才能正式宣布准备好用于生产使用。(这是对整个 P6 生态系统今年预计将经历的全面强化的补充。)JVM 后端有望在 2015 年实现——它有望成为 Perl 6 的初始正式发布的一部分,准备就绪今年的生产使用——但这在很大程度上取决于需求以及有更多开发人员使用它并提供补丁。

  • P6 代码调用 Java 代码是一个额外的项目。在过去的几个月里,Pepe Schwarz 在加快速度、学习代码库和登陆提交方面取得了很大进展。他已经实现了这个答案开头显示的明显更好的短名称调用,并完成了更多用于在 P6 和 Java 类型之间转换的编组逻辑,并且正在积极征求反馈和具体改进的请求。

于 2015-01-12T05:45:34.233 回答
3

负责 Java 互操作这一领域的代码可在类中找到org.perl6.nqp.runtime.BootJavaInterop。它表明重载方法由字符串标识method/<name>/<descriptor>。描述符在函数中计算org.objectweb.asm.Type#getMethodDescriptor。该 jar 可通过来自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();
于 2014-11-26T18:23:07.727 回答
2

我通过以下修改(2018 年 1 月 4 日)使它在 Perl 6.c 上工作:

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
于 2018-01-04T23:06:02.530 回答