[JAVA] Ich habe ein Plug-In erstellt, das Jextract mit Gradle-Aufgaben ausführt

Ich habe ein Gradle-Plug-In erstellt, wie der Titel sagt. Wir bewerben uns derzeit für das Gradle-Repository. Klicken Sie hier für den Quellcode

jnr-ffi Plugin

Dieses Plug-In erleichtert die Verwendung der in der Entwicklung befindlichen Funktionen (die in Java 13 implementiert werden sollen) in Project Panama.

Insbesondere soll JEP 191: Foreign Function Interface komfortabler gestaltet werden.

JNR-bezogene Artikel sind in dieser Qiita zusammengefasst. Bitte zögern Sie nicht, uns zu kontaktieren.

Betriebsumgebung

Version 13 oder höher für System-JDK und Projekt-JDK?

Das zertifizierte JDK lautet Project Panama Early-Access Builds. nur.

Eine Warnmeldung wird ausgegeben, wenn die JDK-Version 12 oder weniger ist, und eine Fehlermeldung wird ausgegeben, wenn Jextract nicht im System-JDK vorhanden ist.

jextract

Was ist Jextrakt?

jextract ist ein Tool, das die entsprechende Java-Schnittstelle aus .h-Dateien wie der C-Sprache generiert.

Es ist an Early-Access-Version von JDK und an Service Loader angehängt. Es kann auch programmgesteuert mit api / java / util / ServiceLoader.html aufgerufen werden.

Jextrakt Aufgabe

Dieses Plug-In definiert eine Aufgabe namens Jextract.

Die Aufgabe jextract verwendet jextract, um eine JAR-Datei (entsprechende Schnittstelle) aus der .h-Datei im angegebenen Ordner zu generieren.

(Es sucht auch nach verschachtelten Dateien und ordnet das Verzeichnis dem Paket zu, um ein JAR zu generieren.)

Optionen für die Jextract-Aufgabe können in build.gradle wie folgt angegeben werden:

build.gradle


jextract{
    // .h Der Pfad des Verzeichnisses, das die Datei enthält
    //Der Anfangswert ist"src/main/resources/"
    sourceRoot = "head/"
    //Pfad des Verzeichnisses zum Ablegen des generierten JAR
    //Der Anfangswert ist"libs/"
    outPath = "jar"
    //Der Stammname des Pakets, zu dem die zu generierende Schnittstelle gehört
    // <packageRoot>.<Verzeichnisname>.<Verzeichnisname>Ist wie benannt
    //Der Anfangswert ist""
    packageRoot = "pkg"
    //Gibt an, ob der Paketname das Verzeichnis sourceRoot enthält
    //Wenn false festgelegt ist, befindet es sich direkt unter SourceRoot..h Das Dateipaket wird zu packageRoot
    //Der Anfangswert ist falsch
    includeRoot = false
}

Produktionsprozess

Jextract anrufen

Rufen Sie jextract mit ServiceLoader auf. Wenn Sie versuchen, com.sun.tools.jextract.Main $ JextractToolProvider direkt aufzurufen, wird übrigens ein Kompilierungsfehler angezeigt. (Liegt es an resources / Message.properties?)

Schreiben wir nun den Java-Code.

Test.java


public class Test{
    public static void main(String[] args){
        //Rufen Sie die Liste der ToolProvider-Implementierungen mit ServiceLoader ab.
        //Diejenigen im JDK-Bin, wie z. B. jshell und jextract, werden zurückgegeben.
        //Der Werkzeugname von jextract lautet"jextract"Verwenden Sie also die passende.
        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("Error:Jextrakt existiert nicht.");
        //Übergeben Sie die Befehlszeilenargumente beim Aufrufen von jextract an das letzte Argumentarray.
        //Trennen Sie Elemente, anstatt sie durch Leerzeichen zu trennen.
        provider.run(System.out, System.err, String[]{"src/main/resources/test.h"});
    }
}

test.h


int hoge(void);

Wenn Sie test.h in src / main / resources / erstellen und Test.main ausführen, wird eine Datei mit dem Namen test.h.jar direkt unter dem Projekt erstellt.

Außerdem werden die diesmal verwendeten Optionen extrahiert.

Möglichkeit Streit Erläuterung
-t Paketnamen Die generierte Schnittstelle gehört zum Paket
-o Dateiname(Einschließlich des Pfades) Dateiname(Pfad)Die generierte JAR-Datei wird in abgelegt
Dateiname(Einschließlich des Pfades) Ich möchte konvertieren.Dateiname der h-Datei(Pfad)
Mehrfachauswahl ist möglich, wird jedoch immer als dasselbe Paket generiert

Zum Beispiel

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

Wenn Sie den Befehl ausführen, oder

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

Als ich das Programm lief

test.h


int hoge(void);

Wenn es eine Datei mit dem Namen out.jar gibt, wird eine Datei mit dem Namen out.jar generiert.

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

Die interne Struktur von out.jar ist wie folgt, und Sie können sehen, dass ein Paketverzeichnis namens pkg generiert wird.

Wenn Sie Test.class mit jad rückwärts kompilieren, sehen Sie, dass es so aussieht:

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

Die .h-Datei ist fest auf die Schnittstelle übertragen.

Als ich es zu einem Plug-In gemacht habe, hat ServiceLoader kein Jextract gefunden. Nachdem ich das System-JDK auf 13 geändert habe, habe ich den Aufruf ein wenig geändert.

public class Test{
    public static void main(String[] args){
        //Verwenden Sie den Systemklassenlader
        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"});
    }
}

Machen Sie ein Plug-In

Ich habe auf diesen Artikel verwiesen.

Dinge, auf die Sie achten sollten

Recommended Posts

Ich habe ein Plug-In erstellt, das Jextract mit Gradle-Aufgaben ausführt
Ich habe mit Swing eine GUI erstellt
Ich habe mit JD-Core eine Befehlszeilenschnittstelle mit dem WinMerge Plugin erstellt
Ich habe mit Ruby einen riskanten Würfel gemacht
Ich habe ein Plug-In für IntelliJ IDEA erstellt
Ich habe eine Janken App mit Kotlin gemacht
Ich habe eine Janken App mit Android gemacht
04. Ich habe mit SpringBoot + Thymeleaf ein Frontend gemacht
Ich habe Mosaikkunst mit Pokemon-Bildern gemacht
Ich habe einen Docker-Container erstellt, um Maven auszuführen
Ich wollte Spring Boot in einem Multiprojekt gradle
Ich habe einen LINE Bot mit Rails + Heroku gemacht
Ich habe versucht, den Block mit Java zu brechen (1)
Ich habe mit Ruby On Rails ein Portfolio erstellt
[Java 11] Ich habe versucht, Java auszuführen, ohne mit Javac zu kompilieren
Ich habe eine Methode entwickelt, um nach Premium Friday zu fragen
[Ruby] Ich habe einen Crawler mit Anemone und Nokogiri gemacht.
Ich möchte eine bestimmte Datei mit WatchService überwachen
Ich habe eine Funktion zum Registrieren von Bildern bei der API in Spring Framework erstellt. Teil 1 (API Edition)
Ich habe versucht, mit Chocolatey eine Java8-Entwicklungsumgebung zu erstellen
Ich habe eine Entwicklungsumgebung mit Rails6 + Docker + PostgreSQL + Materialise erstellt.
Ich habe versucht, eine Java EE-Anwendung mit OpenShift zu modernisieren.
[Rails] Ich habe versucht, eine Mini-App mit FullCalendar zu erstellen
Ich möchte eine mit Rails 6 erstellte App an GitHub senden
[Anfänger] Ich habe ein Programm zum Verkauf von Kuchen in Java erstellt
Ich möchte eine Liste mit Kotlin und Java erstellen!
Ich habe eine Chat-App erstellt.
Ich möchte eine Funktion mit Kotlin und Java erstellen!
Ich habe einen MOD erstellt, der sofort ein Fahrzeug mit Minecraft anruft
[Rails] Ich habe versucht, die Stapelverarbeitung mit der Rake-Task zu implementieren
Selbst in Java möchte ich true mit == 1 && a == 2 && a == 3 ausgeben
Ich habe eine Funktion zum Registrieren von Bildern bei der API in Spring Framework erstellt. Teil 2 (Client Edition)
Ich habe versucht, mit Docker eine Padrino-Entwicklungsumgebung zu erstellen
Ich habe eine Docker-Datei erstellt, um Glassfish 5 mit Oracle Java zu starten
Eine Geschichte, die es Kotlin bequem machte, dass es mühsam ist, Animationen kontinuierlich auf Android auszuführen
Eine Geschichte, die ich mit Java nur schwer herausfordern konnte
[Rails] Ich habe eine einfache Kalender-Mini-App mit benutzerdefinierten Spezifikationen erstellt.
Ich möchte mit link_to [Hinweis] eine Schaltfläche mit einem Zeilenumbruch erstellen.
Legen Sie das Spring-Profil fest, wenn Sie die bootRun-Task mit dem Spring Boot Gradle Plugin ausführen
Ich möchte eine Browsing-Funktion mit Ruby on Rails hinzufügen
[Unity] Ich habe mit NWPathMonitor ein natives Plug-In UniNWPathMonitor erstellt
Ich habe ein Juwel gemacht, um den Text des Org-Modus in Qiita zu posten
Ich habe ein einfaches Suchformular mit Spring Boot + GitHub Search API erstellt.
Erstellt eine Methode zum Anfordern von Premium Friday (Java 8-Version)
[Einführung in JSP + Servlet] Ich habe eine Weile damit gespielt ♬
Ich habe ein Tool erstellt, um den Unterschied zwischen CSV-Dateien auszugeben
Ich möchte mit einem regulären Ausdruck zwischen Zeichenketten extrahieren
Ich habe versucht, mit Rails eine Gruppenfunktion (Bulletin Board) zu erstellen
Ich kann Lombok nicht mit Gradle installieren.
Ich habe versucht, mit Java zu interagieren
Ich habe eine einfache Empfehlungsfunktion erstellt.
So erstellen Sie ein Jenkins-Plug-In
Ich habe eine passende App erstellt (Android App)
Ich habe ein Tool zur Generierung von package.xml erstellt.
[Android] Ich habe eine Schrittzähler-App erstellt.
Ich hatte Probleme bei der Arbeit und habe ein IntelliJ-Plug-In erstellt
Ich möchte im Dialogfeld mehrere Elemente mit einem benutzerdefinierten Layout auswählen