2014-11-26 14 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(); 

purtroppo, questo non funzionaCome posso richiamare un metodo Java da perl6

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

Questo codice è disponibile ai seguenti link. E 'l'unico esempio sono stato in grado di trovare

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

FWIW, [recente discussione Java interoperabilità sul canale IRC freenode # perl6] (http://irclog.perlgeek.de/perl6/2014-11-28#i_9733083). – raiph

+2

Fwiw, nel calendario dell'avvento di quest'anno c'è [Towards cleaner JVM interop] (http://perl6advent.wordpress.com/2014/12/12/day-12-towards-cleaner-jvm-interoperability/). – raiph

risposta

6

risposta finale

Combinando le ripuliture codice spiegato nel La tua risposta ripulito sezione sottostante con i miglioramenti di Pepe Schwarz citati nel Expectation avviso la seguente sezione si ottiene:

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

my $crc = CRC32.new(); 

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

say $crc.getValue(); 

La tua risposta ripulito

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

Un importante po 'cambiato è l'aggiunto .list.

Il frammento 'Hello, Java'.encode('utf-8') restituisce un oggetto, un utf8. Quell'oggetto restituisce un solo valore (stesso) all'istruzione for. Quindi lo for itera solo una volta, passando l'oggetto al blocco di codice con la riga update al suo interno.

Iterando sola volta potrebbe senso se la linea update era .'method/update/([B)V', che associa ad un metodo Java che prevede un buffer di 8 bit interi, che è essenzialmente quello di Perl 6 è utf8.Tuttavia, ciò richiederebbe un certo supporto del codice Perl 6 (presumibilmente nel compilatore principale) per effettuare il marshalling (automagicamente convertito) del Perl 6 utf8 in un Java buf[] e se quel codice è mai esistito/funzionato sicuramente non funziona quando eseguo il test con il ultimo Rakudo.

Ma se si aggiunge un giudizioso .list come mostrato sopra e si modifica il blocco di codice in modo che corrisponda, le cose si risolvono.

Innanzitutto, il .list genera la dichiarazione for che itera su una serie di numeri interi.

In secondo luogo, come te, ho chiamato la versione di Integer arg del metodo Java (.'method/update/(I)V') invece della versione di arg buffer originale e il codice funzionava correttamente. (Ciò significa che la rappresentazione binaria dei unsigned 8 bit interi restituito dall'oggetto Perl 6 utf8 o è già esattamente ciò che il metodo di Java si aspetta o si automagicamente marshalling per voi.)

Un altro cambiamento richiesto è che il from<java> esigenze a essere from<Java> per il tuo commento qui sotto - grazie.

Expectation avviso

A partire dal gennaio 2015:

  • Semplicemente utilizzando il backend JVM per Rakudo/NQP (vale a dire l'esecuzione di codice P6 puro su una JVM) ha ancora bisogno di più indurimento prima che possa essere ufficialmente dichiarato pronto per l'uso produttivo. (Questo è in aggiunta alla tempra a tutto tondo che l'intero ecosistema P6 dovrebbe subire quest'anno.) Il back-end JVM si spera che ci arrivi nel 2015 - si spera che faccia parte del lancio ufficiale iniziale di Perl 6 pronto per produzione utilizzata quest'anno, ma ciò dipenderà in larga misura dalla domanda e da un maggior numero di sviluppatori che lo utilizzano e contribuiscono con le patch.

  • codice P6 che chiama codice Java è un progetto aggiuntivo. Pepe Schwarz ha compiuto grandi progressi negli ultimi due mesi per imparare a usare il codebase e lo landing commits. Ha già implementato la chiamata di shortname ovviamente più bella mostrata all'inizio di questa risposta e completato molto più logiche di marshalling per la conversione tra tipi P6 e Java e sta sollecitando attivamente feedback e richieste di miglioramenti specifici.

+0

Indovinare da https://github.com/rakudo/rakudo/commit/db155f595408610bbd68a14846b3c7dcd1c0734d Direi che il codice di interoperabilità aggiornato dovrebbe leggere '... CRC32: da ;' (con maiuscola 'J'), no? – user7610

+0

Grazie. Fisso.(L'attuale Rakudo ha eseguito il mio codice originale senza un avviso di deprecazione perché il commit non lo deprecava fino a quando la versione taggata 2015.1 non sarà disponibile a fine mese). – raiph

2

Il codice che è responsabile di questa zona di Java interoperabilità si trova nella classe org.perl6.nqp.runtime.BootJavaInterop. Suggerisce che i metodi sovraccaricati sono identificati dalla stringa method/<name>/<descriptor>. Il descrittore è calcolato nella funzione org.objectweb.asm.Type#getMethodDescriptor. Quel barattolo è disponibile tramite Maven dal 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) 
    } 
} 

Questo stampa

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

Da voglio chiamare l'aggiornamento (int) variante di questo metodo sovraccaricato, il metodo corretto invocazione (linea 5 del programma di esempio) è

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

Questo crash con

This representation can not unbox to a native int 

infine, per qualche ragione che non capisco, cambiando la stessa linea per

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

correzioni e l'esempio funziona bene.

La versione finale del codice è

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

(Vedi la mia risposta completa alla tua domanda originale per qualche contesto a questo commento). Il '.Int' nella tua risposta risulta nel passare la lunghezza di' utf8', quindi ottieni il crc per l'intero '11'. Sembra funzionare ma sta dando un risultato fasullo. – raiph

1

Ho ottenuto questo per lavorare su Perl 6.c con le seguenti modifiche (4 gennaio 2018):

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

Con conseguente:

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

% perl6-j crcjava.p6 
1072431491 
Problemi correlati