[JAVA] J'ai créé un plug-in qui exécute jextract avec des tâches Gradle

J'ai fait un plug-in gradle comme le dit le titre. Nous postulons actuellement pour le référentiel gradle. Cliquez ici pour le code source

jnr-ffi Plugin

Ce plug-in facilite l'utilisation des fonctionnalités en cours de développement (à implémenter dans Java 13) dans Project Panama.

En particulier, il est destiné à rendre JEP 191: Interface de fonction étrangère plus pratique.

Les articles liés à JNR sont résumés dans cette Qiita, alors n'hésitez pas à nous contacter.

Environnement d'exploitation

Version 13 ou supérieure pour le JDK système et le projet JDK?

Le JDK certifié est Project Panama Early-Access Builds seulement.

Un message d'avertissement est émis si la version JDK est inférieure ou égale à 12, et un message d'erreur est émis si jextract n'existe pas dans le JDK système.

jextract

Qu'est-ce que jextract?

jextract est un outil qui génère l'interface Java correspondante à partir de fichiers .h tels que le langage C.

Il est attaché à la version à accès anticipé de JDK et est attaché à Service Loader. Il peut également être appelé par programme en utilisant api / java / util / ServiceLoader.html).

tâche jextract

Ce plug-in définit une tâche appelée jextract.

La tâche jextract utilise jextract pour générer un fichier jar (interface correspondante) à partir du fichier .h dans le dossier spécifié.

(Il recherche également les fichiers imbriqués et associe le répertoire au package pour générer un fichier jar.)

Les options de la tâche jextract peuvent être spécifiées dans build.gradle comme suit:

build.gradle


jextract{
    // .h Le chemin du répertoire contenant le fichier
    //La valeur initiale est"src/main/resources/"
    sourceRoot = "head/"
    //Chemin du répertoire pour mettre le fichier jar généré
    //La valeur initiale est"libs/"
    outPath = "jar"
    //Le nom racine du package auquel appartient l'interface à générer
    // <packageRoot>.<Nom du répertoire>.<Nom du répertoire>Est nommé comme
    //La valeur initiale est""
    packageRoot = "pkg"
    //Si le nom du package inclut le répertoire sourceRoot
    //S'il est défini sur false, il est directement sous SourceRoot..h fichier package devient packageRoot
    //La valeur initiale est fausse
    includeRoot = false
}

Processus de production

Appeler jextract

Appelez jextract à l'aide de ServiceLoader. En passant, si vous essayez d'appeler directement com.sun.tools.jextract.Main $ JextractToolProvider, vous obtiendrez une erreur de compilation. (Est-ce à cause de resources / Message.properties?)

Maintenant, écrivons le code Java.

Test.java


public class Test{
    public static void main(String[] args){
        //Obtenez la liste des implémentations de ToolProvider avec ServiceLoader.
        //Ceux du bac JDK, tels que jshell et jextract, seront renvoyés.
        //Le nom d'outil de jextract est"jextract"Alors utilisez celui qui correspond.
        ServiceLoader<ToolProvider> providers = load(ToolProvider.class);
        ToolProvider provider = null;
        for (ToolProvider tool : providers) {
            if (tool.name().equals("jextract")) provider = tool;
        }
        if(provider == null) System.out.println("Erreur:jextract n'existe pas.");
        //Passez les arguments de ligne de commande lors de l'appel de jextract au dernier tableau d'arguments.
        //Séparez les éléments au lieu de les séparer par des blancs.
        provider.run(System.out, System.err, String[]{"src/main/resources/test.h"});
    }
}

test.h


int hoge(void);

Si vous créez test.h dans src / main / resources / et exécutez Test.main, un fichier appelé test.h.jar sera créé directement sous le projet.

De plus, les options utilisées cette fois sont extraites.

option argument La description
-t nom du paquet L'interface générée appartiendra au package
-o nom de fichier(Y compris le chemin) nom de fichier(chemin)Le fichier jar généré est placé dans
nom de fichier(Y compris le chemin) Je veux convertir.nom de fichier du fichier h(chemin)
Plusieurs sélections sont possibles, mais elles sont toujours générées comme le même package

Par exemple

jextract -t pkg -o out.jar test.h

Lorsque vous exécutez la commande, ou

Test.java


public class Test{
    public static void main(String[] args){
        ServiceLoader<ToolProvider> providers = load(ToolProvider.class);
        ToolProvider provider = null;
        for (ToolProvider tool : providers) {
            if (tool.name().equals("jextract")) provider = tool;
        }
        provider.run(System.out, System.err, String[]{"-o", "out.jar", "-t", "pkg", "test.h"});
    }
}

Quand j'ai lancé le programme

test.h


int hoge(void);

S'il existe un fichier appelé out.jar, un fichier appelé out.jar sera généré.

out.jar
|-META-INF
| \jextract.properties
\pkg
  \test.class

La structure interne de out.jar est la suivante, et vous pouvez voir qu'un répertoire de package appelé pkg est généré.

Si vous recompilez Test.class en utilisant jad, vous verrez que cela ressemble à ceci:

Test.jad


// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 

package pkg;


public interface test
{

    public abstract int hoge();
}

Le fichier .h est fermement transpilé vers l'interface.

De plus, quand j'en ai fait un plug-in, ServiceLoader n'a pas trouvé jextract, donc après avoir changé le système JDK en 13, j'ai légèrement changé l'appel.

public class Test{
    public static void main(String[] args){
        //Utiliser le chargeur de classe système
        ServiceLoader<ToolProvider> providers = load(ToolProvider.class, ClassLoader.getSystemClassLoader());
        ToolProvider provider = null;
        for (ToolProvider tool : providers) {
            if (tool.name().equals("jextract")) provider = tool;
        }
        provider.run(System.out, System.err, String[]{"-o", "out.jar", "-t", "pkg", "test.h"});
    }
}

Créer un plug-in

J'ai fait référence à cet article.

Choses à surveiller

Recommended Posts

J'ai créé un plug-in qui exécute jextract avec des tâches Gradle
J'ai créé une interface graphique avec Swing
J'ai créé une interface de ligne de commande avec WinMerge Plugin en utilisant JD-Core
J'ai fait une mort risquée avec Ruby
J'ai créé un plug-in pour IntelliJ IDEA
J'ai créé une application Janken avec kotlin
J'ai créé une application Janken avec Android
04. J'ai fait un frontal avec SpringBoot + Thymeleaf
J'ai fait de l'art de la mosaïque avec des images Pokemon
J'ai créé un conteneur Docker pour exécuter Maven
Je voulais classer la botte à ressort dans un multi-projet
J'ai créé un robot LINE avec Rails + heroku
J'ai essayé de casser le bloc avec java (1)
J'ai fait un portfolio avec Ruby On Rails
[Java 11] J'ai essayé d'exécuter Java sans compiler avec javac
J'ai fait une méthode pour demander la prime vendredi
[Ruby] J'ai fait un robot avec de l'anémone et du nokogiri.
Je souhaite surveiller un fichier spécifique avec WatchService
J'ai créé une fonction pour enregistrer des images avec l'API dans Spring Framework. Partie 1 (édition API)
J'ai essayé de créer un environnement de développement java8 avec Chocolatey
J'ai créé un environnement de développement avec rails6 + docker + postgreSQL + Materialise.
J'ai essayé de moderniser une application Java EE avec OpenShift.
[Rails] J'ai essayé de créer une mini application avec FullCalendar
Je veux pousser une application créée avec Rails 6 vers GitHub
[Débutant] J'ai créé un programme pour vendre des gâteaux en Java
Je veux faire une liste avec kotlin et java!
J'ai créé une application de chat.
Je veux créer une fonction avec kotlin et java!
J'ai créé un MOD qui appelle instantanément un véhicule avec Minecraft
[Rails] J'ai essayé d'implémenter le traitement par lots avec la tâche Rake
Même en Java, je veux afficher true avec un == 1 && a == 2 && a == 3
J'ai créé une fonction pour enregistrer des images avec l'API dans Spring Framework. Partie 2 (édition client)
J'ai essayé de créer un environnement de développement padrino avec Docker
J'ai créé un Dockerfile pour démarrer Glassfish 5 en utilisant Oracle Java
Une histoire qui a rendu pratique avec Kotlin qu'il est difficile d'exécuter une animation en continu sur Android
Une histoire que j'ai eu du mal à défier le pro de la concurrence avec Java
[Rails] J'ai créé une mini-application de calendrier simple avec des spécifications personnalisées.
Je veux créer un bouton avec un saut de ligne avec link_to [Note]
Définir le profil Spring lors de l'exécution de la tâche bootRun avec Spring Boot Gradle Plugin
Je souhaite ajouter une fonction de navigation avec ruby on rails
[Unity] J'ai essayé de créer un plug-in natif UniNWPathMonitor en utilisant NWPathMonitor
J'ai fait un petit bijou pour poster le texte du mode org sur qiita
J'ai créé un formulaire de recherche simple avec Spring Boot + GitHub Search API.
Création d'une méthode pour demander Premium Friday (version Java 8)
[Introduction à JSP + Servlet] J'ai joué avec pendant un moment ♬
J'ai créé un outil pour afficher la différence du fichier CSV
Je veux extraire entre des chaînes de caractères avec une expression régulière
J'ai essayé de créer une fonction de groupe (babillard) avec Rails
Je ne peux pas installer lombok avec Gradle.
J'ai essayé d'interagir avec Java
J'ai fait une simple fonction de recommandation.
Comment créer un plug-in Jenkins
J'ai créé une application correspondante (application Android)
J'ai créé un outil de génération package.xml.
[Android] J'ai créé une application de podomètre.
J'avais des problèmes au travail, j'ai donc créé un plug-in IntelliJ
Je souhaite sélectionner plusieurs éléments avec une disposition personnalisée dans la boîte de dialogue