Jvm 如何从perl6调用Java方法
此代码可从以下链接获得。这是我能找到的唯一的例子Jvm 如何从perl6调用Java方法,jvm,raku,rakudo,java-interop,Jvm,Raku,Rakudo,Java Interop,此代码可从以下链接获得。这是我能找到的唯一的例子 在类中可以找到负责Java互操作这一领域的代码。它表明重载方法由字符串method/标识。描述符在函数org.objectweb.asm.Type#getMethodDescriptor中计算。这个罐子可以通过maven从中获得 import java.util.zip.CRC32 导入org.objectweb.asm.Type 对象方法签名{ def printSignature(cls:Class[\uz],方法:String,参数:C
在类中可以找到负责Java互操作这一领域的代码。它表明重载方法由字符串
method/
标识。描述符在函数org.objectweb.asm.Type#getMethodDescriptor
中计算。这个罐子可以通过maven从中获得
import java.util.zip.CRC32
导入org.objectweb.asm.Type
对象方法签名{
def printSignature(cls:Class[\uz],方法:String,参数:Class[\uz]):单位={
val m=cls.getMethod(方法,参数)
val d=类型.getMethodDescriptor(m)
println(m)
打印项次(s“\t$d”)
}
def main(参数:数组[字符串]){
val cls=类别[CRC32]
#看https://docs.oracle.com/javase/8/docs/api/java/util/zip/CRC32.html
val ab=classOf[Array[Byte]]
val i=classOf[Int]
打印签名(cls,“更新”,ab)
打印签名(cls,“更新”,i)
}
}
这张照片
Method 'method/update/(B)V' not found for invocant of class 'java.util.zip.CRC32'
因为我想调用这个重载方法的update(int)变量,所以正确的方法调用(在示例程序的第5行)是
$crc.'method/update/(I)V'($);
这与
public void java.util.zip.CRC32.update(byte[])
([B)V
public void java.util.zip.CRC32.update(int)
(I)V
最后,由于某种原因我不明白,将同一行更改为
$crc.'method/update/(I)V'($\ Int);
修复了这个问题,示例运行良好
代码的最终版本是
使用v6;
使用java::util::zip::CRC32:from;
my$crc=CRC32.new();
用于“Hello,Java”。编码('utf-8'){
$crc.'method/update/(I)V'($uu.Int);
}
比如$crc.getValue();
最终答案
将下面“您的答案清理”部分中解释的代码清理与下面“期望警报”部分中提到的Pepe Schwarz的改进结合起来,我们得到:
This representation can not unbox to a native int
使用java::util::zip::CRC32:from;
my$crc=CRC32.new();
用于“Hello,Java”。编码('utf-8')。列表{
$crc.update($);
}
比如$crc.getValue();
你的回答清楚了
使用v6;
使用java::util::zip::CRC32:from;
my$crc=CRC32.new();
对于“Hello,Java”.encode('utf-8').list{#追加的`.list`
$crc.'方法/更新/(I)V'($);
}
比如$crc.getValue();
一个重要的更改位是附加的.list
'Hello,Java'.encode('utf-8')
片段返回一个对象,即utf8
。该对象只向for
语句返回一个值(自身)。因此,for的只迭代一次,将对象传递给代码块,其中包含update
行
如果update
行是的method/update/([B)V'
,则只迭代一次是有意义的,它映射到一个Java方法,该方法需要一个8位整数的缓冲区,这基本上就是Perl 6utf8
。然而,这需要一些支持Perl 6代码(可能在核心编译器中)来封送(自动转换)将Perl 6utf8
转换为Javabuf[]
,如果该代码曾经存在/工作过,那么当我使用最新的Rakudo进行测试时,它肯定不工作
但是,如果像上面所示添加一个明智的.list
,并更改代码块以匹配,事情就会解决
首先,.list
生成迭代一系列整数的for
语句
其次,与您一样,我调用了Java方法的Integer arg版本('method/update/(I)V'
),而不是原始的缓冲区arg版本,然后代码正常工作。(这意味着从Perl 6utf8
对象返回的无符号8位整数的二进制表示形式已经完全符合Java方法的要求,或者是自动封送的。)
另一个必需的更改是,根据您下面的评论,from
的必须是from
——谢谢
期望警报
截至2015年1月:
- 仅仅将JVM后端用于Rakudo/NQP(即在JVM上运行纯P6代码)还需要更多的强化,才能正式宣布可以投入生产使用。(这是对整个P6生态系统今年预计将经历的全面强化的补充。)JVM后端有望在2015年实现这一目标——它有望成为今年准备投入生产使用的Perl 6首次正式发布的一部分——但这在很大程度上取决于需求以及更多的开发人员使用它和贡献补丁
- P6代码调用Java代码是一个额外的项目。Pepe Schwarz在过去几个月里在提高速度、学习代码库和代码方面取得了很大的进步。他已经实现了这个答案开头所示的明显更好的短名称调用,并完成了更多P6和Java代码之间转换的封送逻辑nd Java类型,并积极征求反馈和具体改进请求
Fwiw,.Fwiw,在今年的降临节日历中有。我猜更新的互操作代码应该是
…CRC32:from;
(大写J
),没有?谢谢。修复了。(当前的Rakudo运行我的原始代码时没有弃用警告,因为提交直到本月晚些时候发布的标记为2015.1的版本才会弃用它。)(有关此评论的某些上下文,请参阅我对原始问题的完整回答。)答案中的.Int
会传递utf8
的长度,因此您会得到整数11
的crc。它似乎有效,但给出的结果是假的。
This representation can not unbox to a native int
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();
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