2014-11-26 20 views
6
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(); 

leider das nicht funktioniert,Wie rufe ich eine Java-Methode aus Perl6

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

Dieser Code ist unter folgenden Links zur Verfügung. Es ist das einzige Beispiel, das ich habe in der Lage gewesen

  1. Rakudo Perl 6 on the JVM (slides)
  2. Perl 6 Advent Calendar: Day 03 – Rakudo Perl 6 on the JVM
+1

FWIW, [aktuelle Diskussion java Interop auf dem Freenode-IRC-Kanal # perl6] (http://irclog.perlgeek.de/perl6/2014-11-28#i_9733083). – raiph

+2

Fwiw, im diesjährigen Adventskalender gibt es [Towards cleaner JVM interop] (http://perl6advent.wordpress.com/2014/12/12/day-12-towards-cleaner-jvm-interoperability/). – raiph

Antwort

6

endgültige Antwort

den Code Cleanup erklärt in der Ihre Antwort gereinigt Abschnitt weiter unten mit Pepe Schwarzs genannten Verbesserungen in der Erwartung Alarm Kombination Abschnitt unten erhalten wir:

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

my $crc = CRC32.new(); 

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

say $crc.getValue(); 

Ihre Antwort gereinigt

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(); 

Ein wichtiges geändert Bit der beigefügten .list ist.

Das 'Hello, Java'.encode('utf-8') Fragment gibt ein Objekt zurück, utf8. Dieses Objekt gibt nur einen Wert (selbst) an die for-Anweisung zurück. So iteriert der for nur einmal und übergibt das Objekt an den Codeblock mit der update Zeile.

Iterieren nur einmal könnte Sinn machen, wenn die update Linie .'method/update/([B)V' war, die Karten auf eine Java-Methode, die einen Puffer von 8-Bit-Ints erwartet, die im Wesentlichen ist, was ein Perl 6 utf8 ist.Das würde jedoch etwas Unterstützung für Perl 6 Code (vermutlich im Kerncompiler) erfordern, um das Perl 6 utf8 in ein Java buf[] zu marshalieren und wenn dieser Code jemals existiert/gearbeitet hat, funktioniert er sicher nicht, wenn ich mit dem Testcode teste neueste Rakudo.

Aber wenn man einen vernünftigen .list anfügt, wie oben gezeigt, und den Code-Block ändert, um zu entsprechen, funktionieren die Dinge.

Zuerst die .list Ergebnisse in der for Anweisung durchlaufen über eine Reihe von ganzen Zahlen.

Zweitens, wie Sie, rief ich die Integer arg-Version der Java-Methode (.'method/update/(I)V') anstelle der ursprünglichen Puffer arg Version und der Code hat dann richtig funktioniert. (Dies bedeutet, dass die binäre Darstellung des unsigned 8-Bit-Integer von dem Objekt Perl 6 utf8 zurückgegeben wird, ist entweder bereits genau das, was die Java-Methode erwartet oder ist für Sie automatisch serialisiert.)

Eine weitere erforderliche Änderung ist, dass die from<java> Bedürfnisse sei from<Java> per Kommentar unten - danke.

Erwartung Alarm

Ab Januar 2015:

  • Lediglich die JVM Backend für Rakudo/NQP (dh auf einer JVM reinen P6 Code ausgeführt wird) noch mehr Härten muss, bevor es offiziell sein kann für den Produktionseinsatz bereit erklärt. (Dies ist zusätzlich zu der Allround-Verhärtung, die das gesamte P6-Ökosystem in diesem Jahr erfahren wird.) Das JVM-Backend wird hoffentlich im Jahr 2015 ankommen - es wird hoffentlich Teil der ersten offiziellen Einführung von Perl 6 sein, die bereit ist Produktionsnutzung in diesem Jahr - aber das wird weitgehend von der Nachfrage abhängen und davon, dass mehr Entwickler es verwenden und Patches beisteuern.

  • P6-Code aufrufen Java-Code ist ein zusätzliche Projekt. Pepe Schwarz hat in den letzten paar Monaten große Fortschritte gemacht, um auf dem neuesten Stand zu sein. Er lernte die Codebasis und landing commits. Er hat bereits den offensichtlich netteren Kurznamenaufruf implementiert, der zu Beginn dieser Antwort gezeigt wurde, und viel mehr von der Marshalling-Logik zum Umwandeln zwischen P6- und Java-Typen ausgeführt und bittet aktiv um Feedback und Anfragen für spezifische Verbesserungen.

+0

Raten von https://github.com/rakudo/rakudo/commit/db155f595408610bbd68a14846b3c7dcd1c0734d Ich würde sagen, der aktualisierte Interop-Code sollte lesen ... CRC32: von ; '(mit Kapital' J'), nein? – user7610

+0

Danke. Fest.(Der aktuelle Rakudo hat meinen ursprünglichen Code ohne eine Verwarnungswarnung ausgeführt, da der Commit ihn erst dann ablehnt, wenn das Release 2015.1 in diesem Monat markiert wird.) – raiph

2

Der Code zu finden, die für diesen Bereich des Java-Interop verantwortlich ist, wird in der Klasse org.perl6.nqp.runtime.BootJavaInterop gefunden. Es schlägt vor, dass die überladenen Methoden durch die Zeichenfolge method/<name>/<descriptor> identifiziert werden. Der Deskriptor wird in der Funktion org.objectweb.asm.Type#getMethodDescriptor berechnet. Dieses Glas ist erhältlich unter der Nummer http://mvnrepository.com/artifact/asm/asm.

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) 
    } 
} 

Dieser druckt

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

Da ich das Update (int) Variante dieses überladene Methode, die richtige Methodenaufruf (auf der Leitung 5 des Beispielprogramms) nennen wollen, ist

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

Diese Abstürze mit

This representation can not unbox to a native int 

schließlich aus irgendeinem Grunde Ich verstehe nicht, die gleiche Linie zu

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

Korrekturen zu ändern, die und das Beispiel fein läuft.

Die endgültige Version des Codes ist

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

(Siehe meine vollständige Antwort auf Ihre ursprüngliche Frage für einen bestimmten Kontext zu diesem Kommentar.) Die '.Int' in Ihrer Antwort führt dazu, dass Sie die Länge von 'utf8' übergeben, also erhalten Sie den CRC für die ganze Zahl' 11'. Es scheint zu funktionieren, gibt aber ein falsches Ergebnis. – raiph

1

Ich habe dies mit folgenden Änderung (4. Januar 2018) auf Perl 6.c zu arbeiten:

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(); 

in Resultierende:

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

% perl6-j crcjava.p6 
1072431491