J'ai essayé de frapper une méthode Java d'ABCL

introduction

Dans cet article, nous utilisons ABCL (Armed-Bear-Common Lisp), qui est l'un de nos systèmes de traitement Common Lisp et fonctionne sur JVM, pour faire fonctionner des classes et des méthodes écrites en langage Java. La procédure de base est illustrée ci-dessous.

** "Seule l'API pour Java est fournie, mais je souhaite utiliser l'application avec Common Lisp (ci-après dénommée CL)!" **. Il y a, non? Ouais, j'en suis sûr.

** "Mais il n'y a presque pas de documents japonais, je ne suis pas très bon en Clojure, et c'est difficile d'écrire autre que Lisp!" ** Je ne sais pas si quelqu'un est là, mais cet article est basé sur ABCL pour ces personnes. Ceci est un article qui décrit les bases de l'intérieur.

Dans cet article, nous n'appellerons que des méthodes Java simples de CL. J'écrirai les détails dans un article séparé, donc si vous le recherchez, vous risquez de ne rien obtenir, il est donc recommandé de revenir au navigateur.

Documents de référence

C'était le plus (ou le seul) utile.

Au début, je parlais de cela, mais je n'en comprenais pas vraiment le sens et j'en étais accro.

Si vous vous perdez, il peut être judicieux de consulter le code source.

Les informations sur ABCL sont ici, non?

Malheureusement, il n'y a pas de document pour ceux qui ne peuvent lire que le japonais ou ne le savent pas. Il n'est pas rédigé dans un anglais aussi difficile, alors faites de votre mieux pour le lire.

J'espère que cet article vous donnera une idée des bases!

Maintenant, je vais expliquer les spécifications ABCL pour appeler Java à partir de Common Lisp.

Environnement d'exécution

Au cas où, jetons un coup d'œil à cet environnement d'exécution. Cela devrait probablement également fonctionner sur d'autres plates-formes. Je ne l'ai pas vérifié. .. ..

Appel de méthode statique Java

Tout d'abord, je vais expliquer comment appeler une méthode statique. Le code Java simple utilisé pour cet appel est le suivant.

Calc.java


public class Calc {
    public static int addTwoNumbers(int a, int b) {
        return a + b;
    }
}

En tant que méthode statique de la classe Calc, elle effectue un simple travail ** de prise de deux arguments de type entier et de retour de la somme de ceux-ci comme valeur de retour **. Appelons cette méthode addTwoNumbers à partir de Common Lisp. Le code ressemble à ceci (↓)

calc.lisp


(defun add-two-num (num1 num2)
  (let ((result (jstatic "addTwoNumbers" "Calc" num1 num2)))
    result))

jstatic est une fonction intégrée pour appeler des méthodes statiques Java. Le premier argument est le nom de la méthode à appeler (chaîne de caractères) **, le deuxième argument est la classe à laquelle appartient la méthode cible **, et le troisième argument et les suivants sont les ** arguments de méthode **. Lorsqu'il est évalué, le résultat de l'exécution de la méthode est retourné, il est lié au résultat et il est sorti à la fin.

Même si vous regardez l'exemple de programme, seul celui-ci est écrit, mais bien sûr le code Java ne peut pas être appelé tel quel, alors compilez-le et passez-le via le chemin de classe. Je ne sais pas grand-chose à ce sujet, donc si je l'écris pour les gens,

$ javac Calc.java
$ ls
Calc.class Calc.java calc.lisp

Si cela devient, c'est un succès. Si la compilation échoue, quelque chose ne va pas et veuillez vérifier à nouveau. En disant cela, il ne peut y avoir aucune erreur avec cette longueur de code.

Passons à REPL et appelons-le!

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

Vous pouvez l'appeler correctement! add-to-classpath est la fonction intégrée d'ABCL pour transmettre les chemins aux fichiers de classe Java. En Java, vous pouvez passer le chemin de la classe, mais c'est plus facile à lire dynamiquement (vue personnelle).

Appel de méthode dynamique Java

Je ne suis pas si heureux de pouvoir appeler uniquement la méthode Static, alors vérifions la répartition dynamique de la méthode. Le code utilisé pour cet essai est le suivant.

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

Il y a un héros qui a "HP: 100" et "MP: 100" à sa naissance. Il subit un certain nombre de dégâts lorsqu'il est attaqué et consomme des PM lors de l'utilisation de la magie. Si vous vérifiez l'état, les HP et MP restants seront affichés.

Veuillez laisser de côté ce type de conception de classe et pensez que vous avez défini une classe comme celle-ci.

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

Tout d'abord, instanciez cette classe Hero et appelez la méthode showStatus. L'état initial "HP: 100, MP: 100" doit être émis.

Auparavant, j'ai évalué add-to-classpath au niveau supérieur de REPL, mais bien sûr, si vous le mettez dans le fichier Lisp, il sera exécuté au moment du chargement.

jclass prend une chaîne comme argument et renvoie une référence de classe Java avec le nom de cette chaîne. Ce qui est renvoyé ici est un objet de classe, pas une instance.

jnew prend un objet constructeur comme argument et crée une instance. Veuillez noter qu'il ne peut être instancié que si l'objet constructeur est acquis par (jconstructor "nom de classe (chaîne de caractères)") [^ Note 1].

jmethod récupère la méthode à appeler en tant qu'objet. Transmettez l'objet de classe Java et le nom de la méthode, et si nécessaire, le type d'argument class [^ Note 2].

Enfin, passez l'objet méthode acquis précédemment et l'objet instance à jcall et exécutez la méthode.

Lorsque vous l'exécutez réellement, cela devrait ressembler à ce qui suit.

CL-USER> (load "/Path/to/hero.lisp")
T
CL-USER> (hero-status)
"HP: 100, MP: 100"

Ensuite, après avoir utilisé la méthode de réduction HP et la méthode de réduction MP, exécutez la méthode de confirmation d'état. Les deux méthodes soustraire la valeur en passant la valeur à réduire à l'argument.

L'expression Lisp pour appeler ressemble à ceci.

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

Il sera écrit à la manière de Java, mais lorsque vous évaluez réellement cette fonction,

CL-USER> (load "/Path/to/exted-hero.lisp")
T
CL-USER> (extended-hero-status 5 10)
"HP: 95, MP: 90"

Je pense que vous pouvez voir que cela fonctionne correctement.

en conclusion

Qu'as-tu pensé. Avez-vous eu la sensation? Avec ABCL, il peut être possible d'utiliser des bibliothèques Java relativement facilement avec ComonLisp et d'incorporer divers programmes écrits en langage Java dans des projets CL.

Bien que non introduit cette fois, il est bien sûr possible d'appeler Common Lisp depuis le langage Java. Voir la référence utilisateur mentionnée ci-dessus pour plus de détails.

Nous attendons avec impatience vos suggestions et impressions d'erreurs.

[^ Note 1]: J'étais accro à cela parce que je ne comprenais pas l'argument de jnew. [^ Note 2]: Au lieu de passer l'argument lui-même ici, passez l'objet de classe de type de l'argument. Plus précisément, la méthode à distribuer est déterminée en passant quelque chose comme (jclass "int").

Recommended Posts

J'ai essayé de frapper une méthode Java d'ABCL
[Java] J'ai essayé de faire un labyrinthe par la méthode de creusage ♪
java j'ai essayé de casser un simple bloc
J'ai essayé de casser le bloc avec java (1)
J'ai essayé d'exécuter Java dans un terminal Mac
[JDBC] J'ai essayé de faire de l'accès à la base de données SQLite3 depuis Java une méthode pour chaque instruction SQL.
Appeler une méthode avec le bloc de rappel de Kotlin depuis Java
J'ai essayé de créer une compétence Clova en Java
J'ai essayé de créer une fonction de connexion avec Java
J'ai essayé d'utiliser Log4j2 sur un serveur Java EE
J'ai essayé d'appeler du code natif Java / Objective-C depuis Flutter
J'ai essayé OCR de traiter un fichier PDF avec Java
J'ai créé un Wrapper qui appelle KNP depuis Java
J'ai essayé de gratter un graphique boursier en utilisant Java (Jsoup)
Créer une méthode java [Memo] [java11]
J'ai essayé Drools (Java, InputStream)
J'ai essayé d'utiliser Java REPL
J'ai essayé la métaprogrammation avec Java
J'ai essayé de créer un environnement de développement java8 avec Chocolatey
J'ai essayé de moderniser une application Java EE avec OpenShift.
[JDBC] J'ai essayé d'accéder à la base de données SQLite3 depuis Java.
J'ai essayé de convertir une chaîne de caractères en un type LocalDate en Java
J'ai créé un client RESAS-API en Java
J'ai essayé OCR de traiter un fichier PDF avec Java part2
J'ai créé un PDF avec Java.
J'ai créé une application shopify @java
J'ai essayé un petit docker de digdag.
Une personne écrivant C ++ a essayé d'écrire Java
Exécuter le fichier de commandes à partir de Java
J'ai essayé d'interagir avec Java
J'ai essayé la communication UDP avec Java
Accéder à Teradata depuis une application Java
J'ai essayé d'expliquer la méthode
J'ai essayé le framework Java "Quarkus"
J'ai essayé d'utiliser l'API Java8 Stream
J'ai essayé d'utiliser JWT en Java
J'ai essayé de résumer l'apprentissage Java (1)
J'ai essayé de résumer Java 8 maintenant
J'ai essayé d'utiliser le mémo Java LocalDate
J'ai essayé d'utiliser Google HttpClient de Java
[Note] Ce que j'ai appris en six mois grâce à des inexpérimentés (Java)
[Note] Ce que j'ai appris en six mois grâce à des inexpérimentés (Java) (1)
Création d'une méthode pour demander Premium Friday (version Java 8)
[Note] Ce que j'ai appris en six mois grâce à des inexpérimentés (Java) (3)
J'ai essayé de générer une source de programme en langage C à partir de cURL
J'ai essayé d'utiliser l'API Elasticsearch en Java
J'ai essayé un problème de calendrier avec Ruby
Méthode Java
java (méthode)
J'ai essayé d'utiliser UICollectionViewListCell ajouté à partir de Xcode12.
J'ai essayé d'apprendre Java avec une série que les débutants peuvent comprendre clairement
Appel de méthodes Java à partir de JavaScript exécutées en Java
J'ai essayé le mappeur d'objets de Cassandra pour Java
J'ai essayé de résumer les expressions Java lambda
Java9 était inclus, j'ai donc essayé jshell.
J'ai essayé le nouveau yuan à Java
Essayez d'exécuter Kubernetes Job à partir de Java
J'ai essayé de jouer un peu avec BottomNavigationView ①
J'ai essayé d'utiliser OpenCV avec Java + Tomcat
Méthode Java
[Java] méthode