JNI 之数据类型与属性和方法的访问

一、实现工具

     Eclipse的java工程

     vs2010的dll库

二、实现过程

    1、在vs中生成dll动态链接库

     2、然后在java中使用dll库

三、实现流程

1、在java类中创建native方法

2、使用javah方法生成jni头文件

3、把头文件拷贝到vs项目c文件同目录下,然后添加到头文件中

4、引用头文件,实现对应的jni方法

5、生成dll动态内库

6、调用native方法

四、实现

数据类型

基本数据
Java基本数据类型与JNI数据类型的映射关系(在C/C++中用特定的类型来表示Java的数据类型)

boolean jboolean
byte jbyte
char jchar
short jshort
int jint
long jlong
float jfloat
double jdouble
void void

引用类型(对象)
String jstring
object jobject
基本类型的数组也是引用类型
byte[] jByteArray
Class  jclass

java项目目录结构


1、创建native方法

Test.java

package com.test;

import java.util.Random;
import java.util.UUID;

public class Test {
	static{
		System.loadLibrary("Test1");
	}
	
	public String key = "zhangsan";
	
	public static int count = 9;
	
	public native static String getStringFromC();
	
	public native String getString2FromC(int i);

	public native String accessField();
	
	public native void accessStaticField();
	
	public native void accessMethod();
	
	public native void accessStaticMethod();
	
	
	public static void main(String[] args) {
		
		Test t=new Test();
		
		System.out.println(""+t.getStringFromC());
		System.out.println(""+t.getString2FromC(6));
		System.out.println(""+t.accessField());
		t.accessStaticField();
		System.out.println("修改之后的count::::"+count);
		t.accessMethod();
		t.accessStaticMethod();
		
	}
	
	/**
	 * 产生一个指定大小的随机数
	 * @param max
	 * @return
	 */
	public int genRandomInt(int max){
		Random random = new Random();
		return random.nextInt(max);
	}
	
	/**
	 * 删除UUID随机字符串
	 * @return
	 */
	public static String getUUID(){
		UUID uuid = UUID.randomUUID();
		return uuid.toString().replaceAll("-", "");
	}
}
2、使用javah生成jni头文件

D:\Eclipse\workspaces\TestJni\src>javah com.test.Test



注意:到当前类名即可,不用加.java后缀,否则会提示找不到

   有时候类中有中文注释也可能生成失败

  com_test_Test.h    

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

#ifndef _Included_com_test_Test
#define _Included_com_test_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_test_Test
 * Method:    getStringFromC
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_test_Test_getStringFromC
  (JNIEnv *, jclass);

/*
 * Class:     com_test_Test
 * Method:    getString2FromC
 * Signature: (I)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_test_Test_getString2FromC
  (JNIEnv *, jobject, jint);

/*
 * Class:     com_test_Test
 * Method:    accessField
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_test_Test_accessField
  (JNIEnv *, jobject);

/*
 * Class:     com_test_Test
 * Method:    accessStaticField
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_test_Test_accessStaticField
  (JNIEnv *, jobject);

/*
 * Class:     com_test_Test
 * Method:    accessMethod
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_test_Test_accessMethod
  (JNIEnv *, jobject);

/*
 * Class:     com_test_Test
 * Method:    accessStaticMethod
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_test_Test_accessStaticMethod
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

3、然后拷贝生成的头文件到vs项目下

     

把拷贝的头文件放入源文件夹下,然后点击头文件,添加->现有项,然后选中jni.h和jni_md.h和生成的头文件即可

注意:1、因为我们是编写jni所以,需要导入jni.h和jni_md.h,文件来自jdk,搜索到拷贝到源文件目录下添加即可

2、修改生成的头文件中的#include <jni.h> 为  #include "jni.h"

3、修改jni.h头文件中的#include <jni_md.h>为  #include "jni_md.h"

4、实线生成的头文件中的方法

test.c

#define _CRT_SECURE_NO_WARNINGS
#include "com_test_Test.h"
#include <string.h>


JNIEXPORT jstring JNICALL Java_com_test_Test_getStringFromC(JNIEnv * env, jclass jclas){
	return (*env)->NewStringUTF(env, "C String");
}

JNIEXPORT jstring JNICALL Java_com_test_Test_getString2FromC(JNIEnv *env, jobject jobj, jint num){

	return (*env)->NewStringUTF(env, "C  String " + num);

}
//1、访问非静态属性
JNIEXPORT jstring JNICALL Java_com_test_Test_accessField(JNIEnv *env, jobject jobj){
	//jobj是class的对象
	jclass cls = (*env)->GetObjectClass(env, jobj);
	//属性名称,属性签名
	jfieldID fid = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
	//获取对应的属性
	jstring jstr = (*env)->GetObjectField(env, jobj, fid);
	//jstring变成c的字符串
	char* c_str = (*env)->GetStringUTFChars(env, jstr, JNI_FALSE);
	//得到拼接的字符串
	char text[20] = "super  ";

	strcat(text, c_str);
	//把c的字符串变为jstring
	jstring new_jstr = (*env)->NewStringUTF(env, text);
	(*env)->SetObjectField(env, jobj, fid, new_jstr);

	return new_jstr;
}
//访问静态属性
JNIEXPORT void JNICALL Java_com_test_Test_accessStaticField(JNIEnv *env, jobject jobj){
	jclass cls = (*env)->GetObjectClass(env, jobj);
	jfieldID fid = (*env)->GetStaticFieldID(env, cls, "count", "I");
	jint count = (*env)->GetStaticIntField(env, cls, fid);
	count++;
	(*env)->SetStaticIntField(env, cls, fid, count);
}

//2.访问java非静态方法
JNIEXPORT void JNICALL Java_com_test_Test_accessMethod(JNIEnv *env, jobject jobj){
	jclass cls = (*env)->GetObjectClass(env, jobj);
	jmethodID mid = (*env)->GetMethodID(env, cls, "genRandomInt", "(I)I");
	jint random = (*env)->CallIntMethod(env, jobj, mid, 200);
	printf("random num:%ld", random);
}

//访问java静态方法
JNIEXPORT void JNICALL Java_com_test_Test_accessStaticMethod(JNIEnv *env, jobject jobj){
	jclass cls = (*env)->GetObjectClass(env, jobj);
	jmethodID mid = (*env)->GetStaticMethodID(env, cls, "getUUID", "()Ljava/lang/String;");

	jstring uuid = (*env)->CallStaticObjectMethod(env, cls, mid);

	char* uuid_str = (*env)->GetStringUTFChars(env, uuid, JNI_FALSE);
	//拼接
	char filename[100];
	sprintf(filename, "D://%s.txt", uuid_str);
	FILE *fp = fopen(filename, "w");
	fputs("i love jason", fp);
	fclose(fp);
}

注意:1、使用javap -s 文件路径得到方法的签名

                   一定要在bin目录下

              

5、生成dll类库

注意

默认是Win32如果有x64就直接选择,没有就直接新建

配置类型一定要是动态库,默认为应用程序,否则会提示找不到入口

如果是x64一定要到x64的文件夹去找对应的dll文件

6、然后把dll内库复制到项目的根目录下即可

7、加载类库,调用native方法


      

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值