In diesem Artikel verwenden wir ABCL (Armed-Bear-Common Lisp), eines unserer Common Lisp-Verarbeitungssysteme, das mit JVM arbeitet, um Klassen und Methoden zu betreiben, die in Java geschrieben sind. Das grundlegende Verfahren ist unten gezeigt.
** "Es wird nur API für Java bereitgestellt, aber ich möchte die Anwendung mit Common Lisp (im Folgenden als CL bezeichnet) verwenden!" **. Es gibt, richtig? Ja, da bin ich mir sicher.
** "Aber es gibt fast keine japanischen Dokumente, ich bin nicht sehr gut in Clojure und es ist schwer, anders als Lisp zu schreiben!" ** Ich bin nicht sicher, ob jemand da ist, aber dieser Artikel basiert auf ABCL für diese Leute. Dies ist ein Artikel, der die Grundlagen des Inneren beschreibt.
In diesem Artikel werden nur einfache Java-Methoden von CL aufgerufen. Ich werde in einem anderen Artikel über das Durcheinander der Details schreiben. Wenn Sie also danach suchen, erhalten Sie möglicherweise nichts. Daher wird empfohlen, den Browser zurückzusetzen.
Dies war am hilfreichsten (oder nur).
Anfangs habe ich mich darauf bezogen, aber ich habe die Bedeutung nicht wirklich verstanden und war süchtig danach.
Wenn Sie sich verlaufen, ist es möglicherweise eine gute Idee, den Quellcode zu drücken.
Informationen über ABCL sind im Grunde genommen hier, oder?
Leider gibt es kein Dokument für diejenigen, die nur Japanisch lesen oder nicht lesen können. Es ist nicht in so schwierigem Englisch geschrieben, also geben Sie bitte Ihr Bestes, um es zu lesen.
Ich hoffe, dieser Artikel gibt Ihnen einen Eindruck von den Grundlagen!
Jetzt werde ich die ABCL-Spezifikationen für den Aufruf von Java aus Common Lisp erläutern.
Schauen wir uns für alle Fälle diese Ausführungsumgebung an. Es sollte wahrscheinlich auch auf anderen Plattformen funktionieren. Ich habe es nicht überprüft. .. ..
Zunächst werde ich erklären, wie eine statische Methode aufgerufen wird. Der einfache Java-Code, der für diesen Aufruf verwendet wird, ist dieser.
Calc.java
public class Calc {
public static int addTwoNumbers(int a, int b) {
return a + b;
}
}
Als statische Methode der Calc-Klasse führt sie auf einfache Weise ** zwei Argumente vom Typ Integer aus und gibt deren Summe als Rückgabewert zurück **. Nennen wir diese addTwoNumbers-Methode von Common Lisp. Der Code sieht so aus (↓)
calc.lisp
(defun add-two-num (num1 num2)
(let ((result (jstatic "addTwoNumbers" "Calc" num1 num2)))
result))
jstatic ist eine integrierte Funktion zum Aufrufen statischer Java-Methoden. Das erste Argument ist der Name der aufzurufenden Methode (Zeichenfolge) **, das zweite Argument ist die Klasse, zu der die Zielmethode gehört **, und das dritte und nachfolgende Argument sind die ** Methodenargumente **. Bei der Auswertung wird das Ausführungsergebnis der Methode zurückgegeben, an das Ergebnis gebunden und am Ende ausgegeben.
Selbst wenn Sie sich das Beispielprogramm ansehen, wird nur dieses geschrieben, aber natürlich kann der Java-Code nicht so aufgerufen werden, wie er ist. Kompilieren Sie ihn also und übergeben Sie ihn über den Klassenpfad. Wenn ich es für Leute schreibe, weil ich nicht viel darüber weiß,
$ javac Calc.java
$ ls
Calc.class Calc.java calc.lisp
Wenn es wird, ist es ein Erfolg. Wenn die Kompilierung nicht erfolgreich ist, stimmt etwas nicht und überprüfen Sie es erneut. Dabei kann es sein, dass bei dieser Codelänge keine Fehler auftreten.
Fahren wir mit REPL fort und nennen es tatsächlich!
CL-USER> (load "/Path/to/calc.lisp")
T
CL-USER> (add-to-classpath "/Path/to/Calc.java/")
("/Path/to/java-class")
CL-USER> (add-two-num 2 3)
5
CL-UER> (add-two-num -1 9)
8
Sie können es richtig nennen! add-to-classpath ist die in ABCL integrierte Funktion zum Übergeben von Pfaden an Java-Klassendateien. In Java können Sie den Klassenpfad übergeben, dies ist jedoch dynamischer und leichter zu verstehen (persönliche Ansicht).
Ich bin nicht so glücklich, nur die statische Methode aufrufen zu können. Überprüfen wir also den dynamischen Versand der Methode. Der für diesen Test verwendete Code lautet wie folgt.
Hero.java
public class Hero {
private int hp;
private int mp;
public Hero() {
hp = 100;
mp = 100;
}
public void getDamage(int damage){
hp -= damage;
}
public void useMagic(int consumption){
mp -= consumption;
}
public String showStatus(){
return "HP: "+hp+", MP: "+mp;
}
public static void main(String[] argv){
Hero hero = new Hero();
}
}
Es gibt einen Helden, der bei seiner Geburt "HP: 100" und "MP: 100" hat. Es erleidet eine gewisse Menge an Schaden, wenn es angegriffen wird, und verbraucht MP, wenn es Magie einsetzt. Wenn Sie den Status überprüfen, werden die verbleibenden HP und MP angezeigt.
Bitte denken Sie an diese Art von Klassendesign und denken Sie, dass Sie eine Klasse wie diese definiert haben.
hero.lisp
(add-to-classpath "/Path/to/java-class-file")
(defun hero-status ()
(let* ((hero-class (jclass "Hero"))
(hero-instance (jnew (jconstructor "Hero")))
(method (jmethod hero-class "showStatus"))
(result (jcall method hero-instance)))
result))
Instanziieren Sie zuerst diese Hero-Klasse und rufen Sie die showStatus-Methode auf. Der Ausgangszustand "HP: 100, MP: 100" sollte ausgegeben werden.
Früher habe ich Add-to-Classpath auf der obersten Ebene von REPL ausgewertet, aber wenn Sie es in die Lisp-Datei einfügen, wird es natürlich beim Laden ausgeführt.
jclass verwendet eine Zeichenfolge als Argument und gibt eine Java-Klassenreferenz mit dem Namen dieser Zeichenfolge zurück. Was hier zurückgegeben wird, ist ein Klassenobjekt, keine Instanz.
jnew nimmt ein Konstruktorobjekt als Argument und erstellt eine Instanz. Bitte beachten Sie, dass es nur instanziiert werden kann, wenn das Konstruktorobjekt von (jconstructor "Klassenname (Zeichenfolge)") [^ Hinweis 1] erfasst wurde.
jmethod ruft die Methode ab, die als Objekt aufgerufen werden soll. Übergeben Sie das Java-Klassenobjekt und den Methodennamen sowie gegebenenfalls die Argumenttypklasse [^ Hinweis 2].
Übergeben Sie abschließend das zuvor erfasste Methodenobjekt und das Instanzobjekt an jcall und führen Sie die Methode aus.
Wenn Sie es tatsächlich ausführen, sollte es wie folgt aussehen.
CL-USER> (load "/Path/to/hero.lisp")
T
CL-USER> (hero-status)
"HP: 100, MP: 100"
Führen Sie anschließend nach Verwendung der HP-Reduktionsmethode und der MP-Reduktionsmethode die Statusbestätigungsmethode aus. Beide Methoden subtrahieren den Wert, indem sie den zu reduzierenden Wert an das Argument übergeben.
Der Lisp-Ausdruck zum Anrufen sieht folgendermaßen aus.
hero-extend.lisp
(defun extended-hero-status (hp mp)
(let* ((hero-class (jclass "Hero"))
(hero-instance (jnew (jconstructor "Hero")))
(java-int-class (jclass "int"))
(get-damage (jmethod hero-class "getDamage" java-int-class))
(use-magic (jmethod hero-class "useMagic" java-int-class))
(method (jmethod hero-class "showStatus")))
(jcall get-damage hero-instance hp)
(jcall use-magic hero-instance mp)
(let (result (jcall method hero-instance))
result)))
Es wird auf Java-ähnliche Weise geschrieben, aber wenn Sie diese Funktion tatsächlich bewerten,
CL-USER> (load "/Path/to/exted-hero.lisp")
T
CL-USER> (extended-hero-status 5 10)
"HP: 95, MP: 90"
Ich denke, dass Sie sehen können, dass es richtig funktioniert.
Was haben Sie gedacht. Hast du das Gefühl bekommen? Mit ABCL ist es möglicherweise möglich, Java-Bibliotheken mit ComonLisp relativ einfach zu verwenden und verschiedene in der Java-Sprache geschriebene Programme in CL-Projekte zu integrieren.
Obwohl diesmal nicht eingeführt, ist es natürlich möglich, Common Lisp aus der Java-Sprache aufzurufen. Weitere Informationen finden Sie in der oben genannten Benutzerreferenz.
Wir freuen uns auf Ihre Anregungen und Eindrücke von Fehlern.
[^ Anmerkung 1]: Ich war süchtig danach, weil ich das Argument von jnew nicht verstand. [^ Anmerkung 2]: Anstatt das Argument selbst hier zu übergeben, übergeben Sie das Typklassenobjekt des Arguments. Insbesondere wird die zu versendende Methode durch Übergeben von so etwas wie (jclass "int") bestimmt.
Recommended Posts