Home  >  Article  >  System Tutorial  >  How to use JNI to call C/C++ code under Linux

How to use JNI to call C/C++ code under Linux

PHPz
PHPzforward
2024-02-13 15:30:041018browse

Have you ever thought about using C or C features in a Java program? Do you know what JNI is and how it allows you to implement cross-language programming under Linux? If you are interested in these questions, then this article is for you. This article will introduce the basic concepts of JNI, as well as the steps and examples of how to use JNI to call C/C code under Linux.

How to use JNI to call C/C++ code under Linux

Define a Java class — Hello class

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

There are two things to note here:

First: Write a native method declaration for each native method you want to use, except that the native keyword must be specified, as follows:

public native void SayHello(String strName);

Second: The local code library must be loaded explicitly. We need to load this library in the static block of the class (the static library will be called when the class is loaded)

Now we edit hello.java to generate hello.class file.

Generate local link library

To generate a Java local interface header file for the class defined above, you need to use javah. The javah function of the Java compiler will generate the necessary declarations based on the Hello class. This command will generate the Hello.h file

The content of the generated Hello.h file is as follows:

 #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

Create a CPP file Hello.cpp

in the same path as Hello.h

The content is as follows:

#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; 
 }

There are three parameters here. Let’s talk about the parameter usage:

(1) All JNI calls use pointers of type JNIEnv *. It is customary to define this variable as evn in the CPP file, which is the first parameter of any local method. The env pointer points to a function pointer table, and the functions in it can be directly accessed using the "->" operator in VC.
(2) jobject points to a handle to the Java object LocalFunction instantiated in this Java code, which is equivalent to the this pointer.
(3) The third parameter is the parameter passed in by the Java program in the local call. In this example, there is only one String parameter. For string parameters, because Java strings cannot be read directly in native code, they must be converted to C/C strings or Unicode.

Compile and generate shared libraries.

When using GCC, you must tell the compiler where to find the support file for this Java native method, and explicitly tell the compiler to generate position-independent code. In my environment, compile according to the following process:

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

Generate Hello.o

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

Generate libhello.so (this is the file name format of the dynamic link library under Linux, just like the .dll file suffix under Windows)

Finally notify the dynamic linker of the path of this shared file.

export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH

Write a simple Java program to test our native method

Save the following source code as 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");    
  } 
 }

Use javac to compile A.java and generate A.class
Using java A just like executing a normal Java program, we will see Hello world appear on the screen.
Through this article, you should have a preliminary understanding of JNI and how to use JNI to call C/C code under Linux. JNI is a powerful and flexible tool that allows you to take advantage of C/C in a Java program, or take advantage of Java in a C/C program. Of course, JNI also has some shortcomings, such as performance loss, memory leaks, error handling, etc. Therefore, when using JNI, you need to pay attention to some details and specifications to ensure the correctness and security of the code. I hope this article can be helpful to you. If you have any questions or suggestions, please leave a message in the comment area.

The above is the detailed content of How to use JNI to call C/C++ code under Linux. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:lxlinux.net. If there is any infringement, please contact admin@php.cn delete