15 java在linux上jni的编程应用

java里的jni是用于java源码里调用c/c++实现的动态库.
实现步骤:

1 先用eclipse创建一个java工程,新建一个类:

/* Hello.java */
    package com.jk;

    public  class Hello {
       public native void sayhello(String str); //在c/c++库里实现的函数加上native声明, 这个函数成员在这里只要声明,函数体由c/c++实现.
    }

2 写好上面类的代码后, 编译工程(会报没有main函数,没有影响).
接着进入工程源码里生成的bin目录下打开终端里, 使用javah产生头文件
javah -jni com.jk.Hello //它会产生com_jk_Hello.h的头文件, 头文件里已声明我们要实现函数

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

#ifndef _Included_com_jk_Hello
#define _Included_com_jk_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jk_Hello
 * Method:    sayhello
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_jk_Hello_sayhello
  (JNIEnv *, jobject, jstring); // jstring才是参数,前面两个参数是固定的

#ifdef __cplusplus
}
#endif
#endif

3 用一个c源文件实现头文件里声明的函数体.

/* com_jk_Hello.c */

#include <stdio.h>
#include "com_jk_Hello.h"

JNIEXPORT void JNICALL Java_com_jk_Hello_sayhello
  (JNIEnv *env, jobject obj, jstring str)
{
 //把jstring参数转换成c语言里的char *
    const char *data = (*env)->GetStringUTFChars(env, str, 0);

    printf("in jni: %s\n", data);

}

编译成动态库libHello.so时需要指定jdk里的头文件所在路径 :

gcc -shared -fPIC -o libHello.so -I /usr/lib/jvm/java-1.8.0-openjdk/include/  -I /usr/lib/jvm/java-1.8.0-openjdk/include/linux/ com_jk_Hello.c

4 在eclipse里新建一个java工程,在工程里调用动态库libHello.o

/* Hello.java */
package com.jk;

 public class Hello {
    public native void sayhello(String str);
    static {
      System.loadLibrary("Hello"); //注意"Hello"就是表示libHello.so
    }
    public static void main(String args[]) {
        Hello m = new Hello();
        m.sayhello("what");
    }
 }

注意包名,类名必须与步骤1时的一致

5 编译时需要指定libHello.so动态库的路径,否则会报库在java.libary.path里找不到的错误.
指定库的路径: 打开工程属性–> java build path –> libary(库) –> native libary path(本机库位置) –> 用右边的编辑按钮,选中库所在路径.
这里写图片描述



jni里代码在c里使用JNIEnv *env, 需要(*env)->GetStringUTFChars(env, str, 0);
        在c++里,   env->GetStringUTFChars(str, 0);

把jstring转成char *
        c语言: char *data = (*env)->GetStringUTFChars(env, str, 0);
    c++:  char *data = env->GetStringUTFChars(str, 0);

jint可以直接作int变量来使用

把jbyteArray arr转成char数组来用:
    c++:  char *data = env->GetByteArrayElements(arr, 0);
           int len = env->GetArrayLength(arr, 0);

如果需要把传过来的jbyteArray arr数组,改变里面的数据并返回:
   char *data = (char *)env->GetByteArrayElements(arr, 0); 
   int len = env->GetArrayLength(arr);

   //改变arr数组里数据后,设置返回
   env->SetByteArrayRegion(arr, 0, len, (jbyte *)data);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值