Maison  >  Article  >  Tutoriel système  >  Comment utiliser JNI pour appeler du code C/C++ sous Linux

Comment utiliser JNI pour appeler du code C/C++ sous Linux

PHPz
PHPzavant
2024-02-13 15:30:041080parcourir

Avez-vous déjà pensé à utiliser des fonctions C ou C++ dans un programme Java ? Savez-vous ce qu'est JNI et comment il vous permet d'implémenter une programmation multilingue sous Linux ? Si ces questions vous intéressent, alors cet article est fait pour vous. Cet article présentera les concepts de base de JNI, ainsi que les étapes et exemples d'utilisation de JNI pour appeler du code C/C++ sous Linux.

Comment utiliser JNI pour appeler du code C/C++ sous Linux

Définir une classe Java — Bonjour la classe

 public class Hello 
 { 
  static 
  { 
   try 
   { 
 // 此处即为本地方法所在链接库名
    System.loadLibrary("hello"); 
   } 
   catch(UnsatisfiedLinkError e) 
   { 
    System.err.println( "Cannot load hello library:\n " + 
                                e.toString() ); 
   } 
  } 
  public Hello() 
  { 
  } 
 // 声明的本地方法
   public native void SayHello(String strName); 
 }

Il y a deux choses à noter ici :

Tout d'abord : Écrivez une déclaration de méthode native pour chaque méthode native que vous souhaitez utiliser, il vous suffit de préciser le mot-clé natif, comme ceci :

public native void SayHello(String strName);

Deuxième : la bibliothèque de codes locale doit être chargée explicitement. Nous devons charger cette bibliothèque dans le bloc statique de la classe (la bibliothèque statique sera appelée lorsque la classe sera chargée)

Modifions maintenant hello.java pour générer le fichier hello.class.

Générer une bibliothèque de liens locaux

Pour générer le fichier d'en-tête de l'interface locale Java pour la classe définie ci-dessus, vous devez utiliser javah. La fonction javah du compilateur Java générera les déclarations nécessaires basées sur la classe Hello. Cette commande générera le fichier Hello.h

.

Le contenu du fichier Hello.h généré est le suivant :

 #include  
 /* Header for class Hello */ 
 #ifndef _Included_Hello 
 #define _Included_Hello 
 #ifdef __cplusplus 
 extern "C" { 
 #endif 
 /* 
 * Class:     Hello 
 * Method:    SayHello 
 * Signature: (Ljava/lang/String;)V 
 */ 
 JNIEXPORT void JNICALL Java_Hello_SayHello 
  (JNIEnv *, jobject, jstring); 
 #ifdef __cplusplus 
 } 
 #endif 
 #endif

Créez un fichier CPP Hello.cpp dans le même chemin que Hello.h

Le contenu est le suivant :

#include "Hello.h"
 #include  
 // 与 Hello.h 中函数声明相同
 JNIEXPORT void JNICALL Java_Hello_SayHello  (JNIEnv * env, jobject arg, jstring instring) 
 { 
   // 从 instring 字符串取得指向字符串 UTF 编码的指针
 const jbyte *str = 
        (const jbyte *)env->GetStringUTFChars( instring, JNI_FALSE ); 
    printf("Hello,%s\n",str); 
  // 通知虚拟机本地代码不再需要通过 str 访问 Java 字符串。
    env->ReleaseStringUTFChars( instring, (const char *)str ); 
    return; 
 }

Il y a trois paramètres ici. Parlons de l'utilisation des paramètres :

(1) Tous les appels JNI utilisent des pointeurs de type JNIEnv * Il est d'usage de définir cette variable comme evn dans le fichier CPP, qui est le premier paramètre de toute méthode locale. Le pointeur env pointe vers une table de pointeurs de fonctions et les fonctions qu'elle contient sont directement accessibles à l'aide de l'opérateur "->" dans VC.
(2) jobject pointe vers un handle vers l'objet Java LocalFunction instancié dans ce code Java, qui est équivalent au pointeur this.
(3) Le troisième paramètre est le paramètre transmis par le programme Java dans l'appel local. Dans cet exemple, il n'y a qu'un seul paramètre String. Pour les paramètres de chaîne, étant donné que les chaînes Java ne peuvent pas être lues directement dans le code natif, elles doivent être converties en chaînes C/C++ ou Unicode.

Compilez et générez des bibliothèques partagées.

Lorsque vous utilisez GCC, vous devez indiquer au compilateur où trouver le fichier de support pour cette méthode native Java, et indiquer explicitement au compilateur de générer du code indépendant de la position, qui est compilé comme suit dans mon environnement :

gcc -I/home/jbuilder/jdk1.3.1/include 
    -I/home/jbuilder/jdk1.3.1/include/linux -fPIC -c Hello.c

Générer Hello.o

gcc -shared -Wl,-soname,libhello.so -o libhello.so Hello.o

Générer libhello.so (c'est le format de nom de fichier de la bibliothèque de liens dynamiques sous Linux, tout comme le suffixe du fichier .dll sous Windows)

Enfin, informez l'éditeur de liens dynamique du chemin d'accès à ce fichier partagé.

export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH

Écrire un programme Java simple pour tester notre méthode native

Enregistrez le code source suivant sous A.java :

 import Hello; 
 import java.util.*; 
 public class A 
 { 
  public static void main(String argv[]) 
  { 
   A a = new A(); 
  } 
  public A() 
  { 
   Hello h = new Hello(); 
   // 调用本地方法
   h.SayHello("Hello world");    
  } 
 }

Utilisez javac pour compiler A.java et générer A.class
En utilisant Java A, tout comme en exécutant un programme Java normal, nous verrons Hello World apparaître à l'écran.
Grâce à cet article, vous devriez avoir une compréhension préliminaire de JNI et comment utiliser JNI pour appeler du code C/C++ sous Linux. JNI est un outil puissant et flexible qui vous permet de tirer parti du C/C++ dans un programme Java, ou de profiter de Java dans un programme C/C++. Bien entendu, JNI présente également quelques défauts, tels que des pertes de performances, des fuites de mémoire, la gestion des erreurs, etc. Par conséquent, lorsque vous utilisez JNI, vous devez faire attention à certains détails et spécifications pour garantir l'exactitude et la sécurité du code. J'espère que cet article pourra vous être utile. Si vous avez des questions ou des suggestions, veuillez laisser un message dans la zone de commentaires.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer