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'
此代码可从以下链接获得。这是我能找到的唯一例子
答案 0 :(得分:7)
将下面您的答案清理部分中解释的代码清理与Pepe Schwarz在 Expectation alert 部分中提到的改进结合起来,我们得到:
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')
片段返回一个对象utf8
。该对象只返回for
语句中的一个值(本身)。所以for
只迭代一次,将对象传递给代码块,其中包含update
行。
如果update
行是.'method/update/([B)V'
,它会映射到需要8位整数缓冲区的Java方法,那么迭代一次就有意义了,这基本上就是Perl 6 {{1}是的。但是,这需要一些支持Perl 6代码(可能在核心编译器中)来编组(自动转换)Perl 6 utf8
到Java utf8
,如果该代码曾经存在/工作,那么肯定不是我用最新的Rakudo测试时工作。
但是,如果如上所示添加一个明智的buf[]
并更改代码块以匹配,那么事情就会成功。
首先,.list
导致.list
语句迭代一系列整数。
其次,和你一样,我调用了Java方法的整数arg版本(for
)而不是原始缓冲区arg版本,然后代码正常工作。 (这意味着从Perl 6 .'method/update/(I)V'
对象返回的无符号8位整数的二进制表示要么已经完全是Java方法所期望的,要么自动为您编组。)
另一个必要的变化是utf8
下面的评论需要from<java>
- 谢谢。
截至2015年1月:
仅仅使用Rakudo / NQP的JVM后端(即在JVM上运行纯P6代码)仍需要更多强化才能正式宣布准备用于生产。 (这是整个P6生态系统预计将在今年进行的全面强化的补充。)JVM后端有望在2015年实现 - 它有望成为Perl 6首次正式发布的一部分今年的生产使用 - 但这在很大程度上取决于需求,并且有更多的开发人员使用它并提供补丁。
调用Java代码的P6代码是附加项目。 Pepe Schwarz在过去几个月中取得了很大的进步,在学习代码库和landing commits方面取得了进步。他已经实现了在本答案开头显示的明显更好的短名称调用,并完成了更多用于在P6和Java类型之间进行转换的编组逻辑,并且正在积极征求反馈和特定改进请求。
答案 1 :(得分:2)
负责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();
答案 2 :(得分: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