java程序调用c++代码是你需要掌握的

1、准备java代码

首先定义一个包含了native方法的类如下,之后我们要使用这个类中的native方法通过jni调用c++编写成的动态链接库中的方法:


  1. public class JniTest { 
  2.     static
  3.         System.loadLibrary("MyNativeDll"); 
  4.     } 
  5.  
  6.     public static native void callCppMethod(); 
  7.  
  8.     public static void main(String[] args) { 
  9.         System.out.println("DLL path:"+System.getProperty("java.library.path")); 
  10.         callCppMethod(); 
  11.     } 

在代码中主要完成了以下工作:

在静态代码块中,调用loadLibrary方法加载本地的动态链接库,参数为不包含扩展名的动态链接库库文件名。在window平台下会加载dll文件,在linux平台下会加载so文件,在mac os下会加载jnilib文件

声明了一个native方法,native关键字负责通知jvm这里调用方法的是本地方法,该方法在外部被定义

在main方法中,打印加载dll文件的路径,并调用本地方法

2、生成头文件

在使用c/c++来实现本地方法时,需要先创建.h头文件。简单的来说,c/c++程序通常由头文件(.h)和定义文件(.c或.cpp)组成,头文件包含了功能函数、数据接口的声明,而定义文件用于书写程序的实现。

在jdk8中可以直接使用javac -h指令生成c/c++语言中的头文件。如果你使用的是较早版本的jdk,需要在执行javac编译完成class文件后,再执行javah -jni生成c/c++风格的头文件(在jdk10的新特性中已经删除了javah这一指令)。我们使用的jdk8简化了这一步骤,使其可以一步完成,在命令行窗口下执行命令:


  1. javac -h ./jni JniTest.java 

指令中使用 -h参数指定放置生成的头文件的位置,最后的参数是java源文件的名称。在这个过程中完成了两件工作,首先生成class文件,其次在参数指定的目录下生成头文件。生成的头文件com_cn_jni_JniTest.h内容如下:


  1. /* DO NOT EDIT THIS FILE – it is machine generated */ 
  2. #include <jni.h> 
  3. /* Header for class com_cn_jni_JniTest */ 
  4.  
  5. #ifndef _Included_com_cn_jni_JniTest 
  6. #define _Included_com_cn_jni_JniTest 
  7. #ifdef __cplusplus 
  8. extern "C" { 
  9. #endif 
  10. /* 
  11.  * Class:     com_cn_jni_JniTest 
  12.  * Method:    callCppMethod 
  13.  * Signature: ()V 
  14.  */ 
  15. JNIEXPORT void JNICALL Java_com_cn_jni_JniTest_callCppMethod 
  16.   (JNIEnv *, jclass); 
  17.  
  18. #ifdef __cplusplus 
  19. #endif 
  20. #endif 

生成的头文件和大家熟悉的 java接口有些相似,只有函数的声明而没有具体实现。简单的解释一下头文件中的代码:

  • extern "C"告诉编译器,这部分代码使用C语言规则来进行编译
  • JNIEXPORT和JNICALL是jni中定义的两个宏,使用JNIEXPORT支持在外部程序代码中调用该动态库中的方法,使用JNICALL定义函数调用时参数的入栈出栈约定
  • 函数名称由包名+类名+方法名组成,在该方法中有两个参数,通过第一个参数JNIEnv *的对象可以调用jni.h中封装好的大量函数 ,第二个参数代表着native方法的调用者,当java代码中定义的native方法是静态方法时这里的参数是jclass,非静态方法的参数是jobject

接下来我们创建一个cpp文件,引用头文件并实现其中的函数,也就是native方法将要实际执行的逻辑:


  1. #include "com_cn_jni_JniTest.h" 
  2. #include <stdio.h> 
  3.   
  4. JNIEXPORT void JNICALL Java_com_cn_jni_JniTest_callCppMethod 
  5.   (JNIEnv *, jclass) 
  6.     printf("Print From Cpp: \n"); 
  7.     printf("I am a cpp method ! \n"); 

在方法的实现中加入简单的printf打印语句,在完成方法的实现后,我们需要将上面的cpp文件编译为动态链接库,提供给java中的native方法调用,因此下面需要在window环境下安装gcc环境。

【声明】:芜湖站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

相关文章