如何从perl6调用Java方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从perl6调用Java方法相关的知识,希望对你有一定的参考价值。
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'
此代码可从以下链接获得。这是我能找到的唯一例子
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
。该对象只返回一个值(本身)到qazxswpoi语句。所以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类型之间进行转换的编组逻辑,并且正在积极征求反馈和特定改进请求。
负责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" $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();
我在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
以上是关于如何从perl6调用Java方法的主要内容,如果未能解决你的问题,请参考以下文章
如何从片段中调用 getSupportFragmentManager()?