JNI处理是一个转化数据的过程,难点在于java与本地语言交流时的数据转化

 本文通过两个例子来讲解JNI的一个输入/输出应用。首先看一个String的输入输出的例子,下面是java部分的代码 

public class Prompt { 

private native String getLine(String prompt); 

public static void main(String args[]) { 
     Prompt p = new Prompt(); 
     String input = p.getLine("Type a line: "); 
     System.out.println("User typed: " + input); 


static { 
   System.loadLibrary("Prompt"); 
  } 


        native方法是调用c/c++等语言接口的方法,Static静态代码块加载dll文件,本例中dll文件的名称是Prompt.dll。 
编译这个java类,得到class文件,用javah命令生成头文件(javah -jni Prompt),运行成功将获得一个Prompt.h文件,打开该文件可看到以下代码: 

/* DO NOT EDIT THIS FILE - it is machine generated */ 
#include <jni.h> 
/* Header for class Prompt */ 

#ifndef _Included_Prompt 
#define _Included_Prompt 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:     Prompt 
* Method:    getLine 
* Signature: (Ljava/lang/String;)Ljava/lang/String; 
*/ 
JNIEXPORT jstring JNICALL Java_Prompt_getLine 
  (JNIEnv *, jobject, jstring); 

#ifdef __cplusplus 

#endif 
#endif 


以下是一个C语言编写的小代码 
    
    #include <jni.h> 
    #include <stdio.h> 
    #include "Prompt.h" 
    
    JNIEXPORT jstring JNICALL 
    Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt) 
    { 
        char buf[128]; 
        const char *str; 
        str = (*env)->GetStringUTFChars(env, prompt, NULL); 
        if (str == NULL) { 
            return NULL; 
        } 
        printf("%s", str); 
        (*env)->ReleaseStringUTFChars(env, prompt, str); 
        scanf("%s", buf); 
        return (*env)->NewStringUTF(env, buf); 


用vc里的cl可生成dll文件。 

本程序运行过程: 
  运行java程序,main方法内有三句: 
       
       Prompt p = new Prompt(); 
       建立本类实例,这将执行静态块加载dll文件。 
       
       String input = p.getLine("Type a line: "); 
       执行本地方法,我认为这将到头文件Prompt.h中去找执行的方法,于是就找到了这句 
       JNIEXPORT jstring JNICALL Java_Prompt_getLine(JNIEnv *, jobject, jstring); 
  进而执行c语言中的方法 
       执行本方法最困惑的是“如何将java中本地方法的那个String类型的参数转化成C语言中要接收的参数,C语言返回的参数又要转化为java的String”。 
       在 jni.h(应该是在jdk中include文件架下的一个头文件)中定义了基本类型的转换(int - jint , float - jfloat 等),本地代码会调用jni的函数获取相应的内容,例如本例中的GetStringUTFChars函数,该函数将JString转化为了C语言中的String,然后可以作为标准的C语言变量使用,处理后返回一个jString变量。 
       
       System.out.println("User typed: " + input); 
       打印结果。 
       
       下面看另外一个例子。 
       java代码: 

       public class InstanceFieldAccess { 
       
       private String s; 
       
       private native void accessField(); 
       
       public static void main(String args[]) { 
               InstanceFieldAccess c = new InstanceFieldAccess(); 
               c.setS("abc"); 
               c.accessField(); 
               System.out.println("In Java:"); 
               System.out.println("  c.s = \"" + c.getS() + "\""); 
           } 
           static { 
               System.loadLibrary("InstanceFieldAccess"); 
           } 
           
        public void setS(String s) 
        { 
            this.s = s; 
        } 
        
        public String getS() 
        { 
           return s; 
        ) 
           
      } 
      
      以下是C语言代码: 
      
      #include <jni.h> 
      #include <stdio.h> 
      #include "InstanceFieldAccess.h"  
      
      JNIEXPORT void JNICALL 
      Java_InstanceFieldAccess_accessField(JNIEnv *env, jobject obj) 
      { 
          jfieldID fid;   /* store the field ID */ 
          jstring jstr; 
          const char *str; 
      
         //获取java类实例 
          jclass cls = (*env)->GetObjectClass(env, obj); 
      
          printf("In C:\n"); 
      
         //获取java类实例的变量s 
          fid = (*env)->GetFieldID(env, cls, "s", 
                                   "Ljava/lang/String;"); 
          if (fid == NULL) { 
              return; /* failed to find the field */ 
          } 
      
         //获取变量s的值 
          jstr = (*env)->GetObjectField(env, obj, fid); 
         //将变量s的值转化为标准c语言能处理的类型 
         str = (*env)->GetStringUTFChars(env, jstr, 0); 
          if (str == NULL) { 
              return; /* out of memory */ 
          } 
          printf("  c.s = \"%s\"\n", str); 
          //将str转化为jString 类型 
          (*env)->ReleaseStringUTFChars(env, jstr, str); 
      
          //修改jString 值为 “123”; 
          jstr = (*env)->NewStringUTF(env, "123"); 
          (*env)->SetObjectField(env, obj, fid, jstr); 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值