JNI-Java访问C库

JNI字段描述符
  • 用"["表示数组,比如"int []"表示为"[I"
  • 对于类,要用全称"L包.子包.类名;"(前面有"L",后面有";"),比如"Ljava/lang/String;"
  • 除String类外,其他的类都用Object表示,即"Ljava/lang/Object;"

native.c
/*
编译:gcc -I/usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -fPIC -shared -o libnative.so native.c
*/

#include <stdio.h>
#include <stdlib.h>
#include <jni.h> //usr/lib/jvm/java-1.7.0-openjdk-amd64/include/jni.h

#if 0
typedef struct {
	char *name;			/* java里调用的函数名 */
	char *signature;	/* JNI字段描述符,用来表示Jave里调用的函数的参数和返回值类型 */
	void *fnPtr;		/* C语言实现的本地函数 */
}JNINativeMethod;
#endif


/*
注意:C函数比Java里的声明多2个参数: (JNIEnv *env, jclass cls)
*/
void c_hello(JNIEnv *env, jobject cls)
{
	printf("hello world!\n");
}

/*
	形参:int
	返回值:int
*/
jint c_myprintf(JNIEnv *env, jobject cls, jint m)
{
	printf("hello world! %d\n",m);
	return 100;
}

/*
	形参:String
	返回值:String
*/
jstring JNICALL c_display_string(JNIEnv *env, jobject cls, jstring str)
{
	//printf("this is c : %s\n",str);
	//return "return from C";

    const jbyte *cstr;
    cstr = (*env)->GetStringUTFChars(env, str, NULL);
    if (cstr == NULL) {
        return NULL; /* OutOfMemoryError already thrown */
    }
    printf("get string from java:%s\n", cstr);
	(*env)->ReleaseStringUTFChars(env, str, cstr);

	return (*env)->NewStringUTF(env, "return from c");

}

/*
	形参:传入数组
	返回值:int
*/
jint JNICALL c_display_data(JNIEnv *env, jobject cls, jintArray arr)
{
	jint *carr;
    jint i, sum = 0;

    carr = (*env)->GetIntArrayElements(env, arr, NULL);
    if (carr == NULL) {
        return 0; /* exception occurred */
    }
    for (i = 0; i < (*env)->GetArrayLength(env,arr); i++) {
        sum += carr[i];
    }
    (*env)->ReleaseIntArrayElements(env, arr, carr, 0);

    return sum;
}

/*
 * Class:     JNIDemo
 * Method:    display_array
 * Signature: ([I)[I
 *
 * 形参:传入数组
 * 返回值:输出数组
 */
jintArray JNICALL c_display_array(JNIEnv *env, jobject cls, jintArray arr)
{

	jint *carr;
	jint *oarr;
	jintArray rarr;
    jint i, n = 0;

    carr = (*env)->GetIntArrayElements(env, arr, NULL);
    if (carr == NULL) {
        return 0; /* exception occurred */
    }
	n = (*env)->GetArrayLength(env,arr);

	oarr = malloc(sizeof(jint)*n);
	if(oarr == NULL) {
		(*env)->ReleaseIntArrayElements(env, arr, carr, 0);
		return 0;
		
	}
	for(i = 0; i < n; i++) {
		oarr[i] = carr[n-1-i];
	}

	/*Creates an jint array with thegiven length.*/
	rarr = (*env)->NewIntArray(env,n);
	if(rarr == NULL) {
		(*env)->ReleaseIntArrayElements(env, arr, carr, 0);
		return 0;
	}
	/*Copies the contents of primitive arrays to or from a preallocated C buffer.	
	void (JNICALL *SetIntArrayRegion)
		  (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf);
	*/
	(*env)->SetIntArrayRegion(env,rarr,0,n,oarr);

    (*env)->ReleaseIntArrayElements(env, arr, carr, 0);
	free(oarr);

    return rarr;
}

/* 
定义一个映射数组JNINativeMethod[]
可以注册多个本地函数
*/
static const JNINativeMethod methods[] = {
	{"hello","()V",(void *)c_hello},
	{"myprintf","(I)I",(void *)c_myprintf},
	{"display_string","(Ljava/lang/String;)Ljava/lang/String;",(void *)c_display_string},
	{"display_data","([I)I",(void *)c_display_data},
	{"display_array","([I)[I",(void *)c_display_array},
};


/* 只要java 加载库System.loadLibrary      就会执行该函数          */
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *jvm, void *reserved)
{
    JNIEnv *env;
    jclass cls;

	/* 获得运行环境 */
    if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {
        return JNI_ERR; /* JNI version not supported */
    }
    cls = (*env)->FindClass(env, "JNIDemo");
    if (cls == NULL) {
        return JNI_ERR;
    }

	/* 建立联系 java<--->c*/
	if((*env)->RegisterNatives(env,cls,methods,5) < 0)
		return JNI_ERR;
	
    return JNI_VERSION_1_4;
}


JNIDemo.java
/*
编译:		javac JNIDemo.java
		export LD_LIBRARY_PATH=.
		java JNIDemo

自动生成字段描述符:
		javac JNIDemo.java
		javah -jni JNIDemo
*/

public class JNIDemo {

	/* 静态代码块,加载库只执行一次 */
		static {
			/* 1. load 加载libnative.so */
			System.loadLibrary("native");/* libnative.so */
		}

	//public native static void hello();//声明
	public native void hello();//声明
	public native int myprintf(int m);
	public native String display_string(String str);
	public native int display_data(int a[]);
	public native int[] display_array(int a[]);

	public static void main(String args[]){

		JNIDemo d = new JNIDemo();
		int a[] = {1, 2, 3, 4, 5};
		int b[] = null;
		int i;
		/* 2. java <--> c 建立映射关系 */

		/* 3.调用 */
		d.hello();
		System.out.println(d.myprintf(123));
		System.out.println(d.display_string("this is java jni demo"));
		System.out.println(d.display_data(a));
		b = d.display_array(a);

		for(i = 0; i < b.length; i++)
			System.out.println(b[i]);
	}
}

调试结果:



                                                                                                                          参考学习韦东山java视频整理
                                                                                                                                              2017-07-25


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值