JNI中Java和C的基情

JNI中相互调用

java调用c/c++生成的dll库.

  • 在java中编写native方法
  • javac , javah 生成头文件
  • 编辑源文件,针对头文件,用c/c++以及JNI中的函数实现方法,
  • 生成dll文件,放在配置了环境变量的文件夹中
  • 在java文件中 loadlibrary直接调用

c/c++调用java属性以及方法.

调用遵循一个规律:

在c文件中,实现相应方法(JNIEnv *env, jobject jobj),
流程为(具体实现不尽相同):
1.jclass cls = (*env)->GetObjectClass(env, jobj);
2.jfieldID fid = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
  其中的属性/方法名,以及签名可变,签名从javap -s -p class完整路径类名 得到(在bin的class目录下寻找).
3.jint jit=(*env)->GetStaticIntField(env, jcs, fid);  //属性
 //调用//CallStatic<Type>Method
 jstring uuid = (*env)->CallStaticObjectMethod(env, cls, mid);
4.对JNI类型进行操作

5.如果带有返回值,则需要再将内容返回(c->jni) 
    //修改k//Set<Type>Field 
    (*env)->SetObjectField(env, jobj, fid, new_jstr);

完整源文件

  • ###相关java文件
package com.ccj.jni;

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



public class JniDemo {

    public String key = "ccj";

    public static int count = 9;

    public native static String getStringFromC();

    public native String getStringFromC2(int i);
    //访问属性,返回修改之后的属性内容
    public native String accessField();

    public native void accessStaticField();

    public native void accessMethod();

    public native void accessStaticMethod();

    public static void main(String[] args) {
        String text = getStringFromC();
        System.out.println(text);
        JniDemo t = new JniDemo();
        text = t.getStringFromC2(6);
        System.out.println(text);

        System.out.println("key修改前:"+t.key);
        t.accessField();
        System.out.println("key修改后:"+t.key);

        System.out.println("count修改前:"+count);
        t.accessStaticField();
        System.out.println("count修改后:"+count);

        t.accessMethod();
        t.accessStaticMethod();
    }

    //产生指定范围的随机数
    public int genRandomInt(int max){
        System.out.println("genRandomInt 执行了...");
        return new Random().nextInt(max); 
    }

    //产生UUID字符串
    public static String getUUID(){
        return UUID.randomUUID().toString();
    }

    //加载动态库
    static{ 
        System.loadLibrary("Project5");
    }

}

  • ###相关c文件

#define _CRT_SECURE_NO_WARNINGS
#include "com_ccj_jni_JniDemo.h"
#include <string.h>
#include <stdlib.h>
#include <string.h>

/**********************java调用C********************************/
/* * Class: com_ccj_jni_JniDemo * Method: getStringFromC java调用C * Signature: ()Ljava/lang/String; */
JNIEXPORT jstring JNICALL Java_com_ccj_jni_JniDemo_getStringFromC
(JNIEnv * env, jclass jcs){

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

}


/* * Class: com_ccj_jni_JniDemo * Method: getStringFromC2 * Signature: (I)Ljava/lang/String; */
JNIEXPORT jstring JNICALL Java_com_ccj_jni_JniDemo_getStringFromC2
(JNIEnv *env, jobject job, jint jint){
        int num = jint + 2;
        char *temp = "num is:";
        //strcat(temp,num);
        return (*env)->NewStringUTF(env, temp);


};
/**********************C调用java********************************/
/* * Class: com_ccj_jni_JniDemo * Method: accessField 调用属性key,并修改 * 方法:fid->field->变为char->用c修改->jstring->Set<Type>Field * Signature: ()Ljava/lang/String; */
JNIEXPORT jstring JNICALL Java_com_ccj_jni_JniDemo_accessField
(JNIEnv *env, jobject jobj){
        //jobj是t对象,JniTest.class
        jclass cls = (*env)->GetObjectClass(env, jobj);
        //jfieldID
        //属性名称,属性签名
        jfieldID fid = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");

        //jason >> super jason
        //获取key属性的值
        //Get<Type>Field
        jstring jstr = (*env)->GetObjectField(env, jobj, fid);
        printf("jstr:%#x\n", &jstr);


        //jstring -> c字符串
        //isCopy 是否复制(true代表赋值,false不复制)
        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);

        //修改key
        //Set<Type>Field
        (*env)->SetObjectField(env, jobj, fid, new_jstr);

        printf("new_jstr:%#x\n", &new_jstr);

        return new_jstr;

}

/* * Class: com_ccj_jni_JniDemo * Method: accessStaticField 修改Java中count值 * Signature: ()V */
JNIEXPORT void JNICALL Java_com_ccj_jni_JniDemo_accessStaticField
(JNIEnv *env, jobject job){
    jclass jcs=(*env)->GetObjectClass(env,job);
    jfieldID fid = (*env)->GetStaticFieldID(env, jcs, "count", "I");

    jint jit=(*env)->GetStaticIntField(env, jcs, fid);

    jit++;
    //printf("niDemo_accessStaticField:%s\n", jit);
    (*env)->SetStaticIntField(env, jcs, fid, jit);

};

/* * Class: com_ccj_jni_JniDemo * Method: accessMethod * Signature: ()V */
JNIEXPORT void JNICALL Java_com_ccj_jni_JniDemo_accessMethod
(JNIEnv *env, jobject job){

    jclass jcs = (*env)->GetObjectClass(env, job);
    jfieldID fid = (*env)->GetMethodID(env, jcs, "genRandomInt", "(I)I");
    jint jit=(*env)->CallIntMethod(env, job, fid);

    printf("Java_com_ccj_jni_JniDemo_accessMethod%s\n", jit);



};

/* * Class: com_ccj_jni_JniDemo * Method: accessStaticMethod 调用方法对filefile进行操作 * Signature: ()V */
JNIEXPORT void JNICALL Java_com_ccj_jni_JniDemo_accessStaticMethod
(JNIEnv *env, jobject job){
    //jclass
    jclass cls = (*env)->GetObjectClass(env, job);
    //jmethodID 
    jmethodID mid = (*env)->GetStaticMethodID(env, cls, "getUUID", "()Ljava/lang/String;");

    //调用
    //CallStatic<Type>Method
    jstring uuid = (*env)->CallStaticObjectMethod(env, cls, mid);

    char * uuid_str = (*env)->GetStringUTFChars(env,uuid,NULL);

    char *fileName[100];

    sprintf(fileName, "D:\\%s.txt", uuid_str);

    FILE *file = fopen(fileName,"w");
    fputs("Hellow Method",file);
    fclose(file);
};

你可能感兴趣的:(java,jni,C语言,native)