JNI中C调用Java方法

背景需求

  我们需要在JNI的C代码调用Java代码。实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用。

JNI关键方法讲解。

1. 在同一个类中,调用其他方法

JNIEXPORT void JNICALL Java_cn_itcast_ndkcallback_DataProvider_callmethod1
  (JNIEnv * env, jobject obj){
    //在c代码里面调用java代码里面的方法
    // java 反射
    //1 . 找到java代码的 class文件
    //    jclass      (*FindClass)(JNIEnv*, const char*);
    jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");
    if(dpclazz==0){
        LOGI("find class error");
        return;
    }
    LOGI("find class ");

    //2 寻找class里面的方法
    //   jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
    jmethodID method1 = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");
    if(method1==0){
        LOGI("find method1 error");
        return;
    }
    LOGI("find method1 ");
    //3 .调用这个方法
    //    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    (*env)->CallVoidMethod(env,obj,method1);
}

注意: 看红色的内容,如何获得呢? 这个是函数的签名。函数签名借住命令 javap来获得,放到第二个参数即可。

这样就可以调用DataProvider中的helloFromJava方法了。

2. 上面的方法是调用的返回值为void的java方法。如果想调用其他类型的。JNI中还提供的许多其他返回类型的方法。

    jobject     (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
    jobject     (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jobject     (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jboolean    (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
    jboolean    (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jboolean    (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jbyte       (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
    jbyte       (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jbyte       (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jchar       (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
    jchar       (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jchar       (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jshort      (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
    jshort      (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jshort      (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
    jint        (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jint        (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jlong       (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
    jlong       (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jlong       (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jfloat      (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...) __NDK_FPABI__;
    jfloat      (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list) __NDK_FPABI__;
    jfloat      (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) __NDK_FPABI__;
    jdouble     (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...) __NDK_FPABI__;
    jdouble     (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list) __NDK_FPABI__;
    jdouble     (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) __NDK_FPABI__;
    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    void        (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    void        (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);

3. 如果java中的方法是静态的,就需要调用GetStaticMethodID 和 CallStaticVoidMethod 方法。

JNIEXPORT void JNICALL Java_cn_itcast_ndkcallback_DataProvider_callmethod4
  (JNIEnv * env, jobject obj){
      //1 . 找到java代码的 class文件
        //    jclass      (*FindClass)(JNIEnv*, const char*);
        jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");
        if(dpclazz==0){
            LOGI("find class error");
            return;
        }
        LOGI("find class ");

        //2 寻找class里面的方法
        //   jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
        // 注意 :如果要寻找的方法是静态的方法 那就不能直接去获取methodid
        //jmethodID method4 = (*env)->GetMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V");
        //    jmethodID   (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);
        jmethodID method4 = (*env)->GetStaticMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V");
        if(method4==0){
            LOGI("find method4 error");
            return;
        }
        LOGI("find method4 ");

        //3.调用一个静态的java方法
        //    void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
        (*env)->CallStaticVoidMethod(env,dpclazz,method4,(*env)->NewStringUTF(env,"static haha in c"));
}

4. 如果C调用的Java方法不在一个类中。

分析:JNI提供的方法都有两个参数:(JNIEnv *env , jobject obj)。 env是JNI提供的方法集合。 obj是上线文。下面的例子的obj不是所需要的上下午,所以要重新创建。

//obj DemoActivity
 JNIEXPORT void JNICALL Java_cn_itcast_ndkcallback_DemoActivity_call_1dp_1method1
  (JNIEnv * env, jobject obj){
    //在c代码里面调用java代码里面的方法
        // java 反射
        //1 . 找到java代码的 class文件
        //    jclass      (*FindClass)(JNIEnv*, const char*);
        jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");
        if(dpclazz==0){
            LOGI("find class error");
            return;
        }
        LOGI("find class ");

        //2 寻找class里面的方法
        //   jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
        jmethodID method1 = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");
        if(method1==0){
            LOGI("find method1 error");
            return;
        }
        LOGI("find method1 ");
        //3 .调用这个方法
        //    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
        //    jobject     (*NewObject)(JNIEnv*, jclass, jmethodID, ...);
        //  jobject     (*AllocObject)(JNIEnv*, jclass);
        jobject dpobj= (*env)->AllocObject(env,dpclazz);

        (*env)->CallVoidMethod(env,dpobj,method1);
}

5. 提示

为了避免4中的内容,我们尽量让C要调用的Java方法在同一个类中

时间: 2024-10-12 09:07:07

JNI中C调用Java方法的相关文章

jni中调用java方法获取当前apk的签名文件md5值

相应的java方法: void getsign(Context context) throws Exception { PackageInfo localPackageInfo = context.getPackageManager() .getPackageInfo(context.getPackageName(), 64); StringBuilder localStringBuilder = new StringBuilder(); Signature[] arrayOfSignature

cocos2d-x中使用JNI的调用JAVA方法

用cocos2d-x公布Android项目时.都应该知道要用JAVA与C/C++进行交互时会涉及到JNI的操作(Java Native Interface).JNI是JAVA的一个通用接口.旨在本地化语言(如C\C++)与JAVA语言进行交互.在交互过程成中,JAVA调用的是已编译好的本地化语言的二进制代码(如Windows下的dll.Linux下的so文件).所以在交叉编译时看到Eclipse的控制台输出 [armeabi] SharedLibrary  : libcocos2dcpp.so

java native interface JNI 调用Java方法

在上一篇文章中介绍了JNI,以及java调用JNI,这篇讲一下 JNI调用java方法. 通过使用合适的JNI函数,你可以创建Java对象,get.set 静态(static)和 实例(instance)的域,调用静态(static)和实例(instance)函数.JNI通过ID识别域和方法,一个域或方法的ID是任何处理域和方法的函数的必须参数. 下表列出了用以得到静态(static)和实例(instance)的域与方法的JNI函数.每个函数接受(作为参数)域或方法的类,它们的名称,符号和它们对

Android Studio NDK开发-JNI调用Java方法

相对于NDK来说SDK里面有更多API可以调用,有时候我们在做NDK开发的时候,需要在JNI直接Java中的方法和变量,比如callback,系统信息等.... 如何在JNI中调用Java方法呢?就需要先了解FindClass和GetMethodID了. FindClass和GetMethodID 在JNI中可以通过FindClass可以找到Java类,得到jclass,例如: jclass clz=(*env)->FindClass(env,"com/jjz/JniHandle"

jsp中怎么调用java类中的方法

在jsp页面中先要,引入java类 例如: <%@page import="javabean.DbConn"%><!-- 引入包中的"类" --> <!--在用到的地方,直接对类实例化--> <% DbConn  DB=new  DbConn(); %> <!--然后就可以直接调用类中的方法--> <% Connection con=DB.conn(); %> jsp中怎么调用java类中的方法

C#调用Java方法

C#调用Java方法(详细实例) 阅读目录 C#调用c++ C#调用JAVA方法 C#可以直接引用C++的DLL和转换JAVA写好的程序.最近由于工作原因接触这方面比较多,根据实际需求,我们通过一个具体例子把一个JAVA方法转换成可以由C#直接调用的DLL 回到目录 C#调用c++ C#调用C++的例子网上很多,以一个C++的具体方法为例. C++代码 // 获取一帧图像数据 MVSMARTCAMCTRL_API int __stdcall MV_SC_GetOneFrame(IN void*

C#调用Java方法(详细实例)

C#调用c++ C#调用C++的例子网上很多,以一个C++的具体方法为例. C++代码 // 获取一帧图像数据MVSMARTCAMCTRL_API int __stdcall MV_SC_GetOneFrame(IN void* handle,                                                    IN OUT unsigned char *pData ,                                               

C++调用Java方法时jvm.dll相关错误 【每次记录完后都被瞬间解决了……】

在编程的学习过程中,愈发感觉到了女性思维在这方面的局限性. 背景介绍: 为了学习JNI中C++对Java的调用,在阅读<JNI技术手册>的同时加以练习.但根据示例代码编写过程中总出现各种 奇怪的问题(一度后悔自己装了win7 64位系统,而电脑之前是预装win8 32位的...).由于Java部分的代码非常简单, 没有出现任何错误,javac.javah命令也能正常输出.class文件和头文件.但C++部分却报错了.所学习的示例代码意图 通过C++调用Java,生成一个.exe的启动文件. J

JNI由浅入深_7_c调用Java方法一

1.在Java中声明方法 <span style="font-size:14px;">/** * javah -encoding utf-8 -jni com.example.jniandroid.service.CFunction * 当java中有中文时,会报编码GBK不可映射字符 方法的调用,加上-encoding utf-8 * * @author libin * */ public class CFunction { /** * 实现在c里面回调callback方