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.
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
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).
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
}
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"});
}
}
J'ai fait référence à cet article.
Recommended Posts