`
kongweile
  • 浏览: 517373 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

C通过JNI 层调用Java的静态和非静态方法

 
阅读更多

1、主要流程

1、  新建一个测试类TestProvider.java

a)         该类提供了2个方法

b)        一个静态的方法,一个非静态的方法

2、  JNI中新建Provider.c

a)         该文件中需要把Java中的类TestProvider映射到C

b)        TestProvider的两个方法映射到C

c)         新建TestProvider 对象

d)        调用两个方法

3、  Android 上层 调用 JNI

4、  JNI层调用C

5、  层调用 Java 方法

 

2、设计实现

1、界面设计如下:


老样子,很搓,不过实用,嘿嘿

代码不在这贴出了,有需要的兄弟直接到文章结束部分下载。

 

 

2、      关键代码说明

C中定义映射的类、方法、对象

jclass TestProvider;

jobject mTestProvider;

jmethodID getTime;

jmethodID sayHello;

 

中映射 

       TestProvider = (*jniEnv)->FindClass(jniEnv,"com/duicky/TestProvider");

C中新建对象

       jmethodID construction_id = (*jniEnv)->GetMethodID(jniEnv, TestProvider,"<init>", "()V");

TestProvider mTestProvider = (*jniEnv)->NewObject(jniEnv, TestProvider,construction_id);

中映射方法

       静态:

getTime = (*jniEnv)->GetStaticMethodID(jniEnv, TestProvider, "getTime","()Ljava/lang/String;");

       非静态:

sayHello = (*jniEnv)->GetMethodID(jniEnv, TestProvider, "sayHello","(Ljava/lang/String;)V");

中调用 Java 方法

       静态:

(*jniEnv)->CallStaticObjectMethod(jniEnv, TestProvider, getTime);

       非静态:

(*jniEnv)->CallVoidMethod(jniEnv, mTestProvider, sayHello,jstrMSG);

 

注意 GetXXXMethodID   CallXXXMethod 

第一个XXX 表示的是映射方法的类型,如: 静态 跟非静态

第二个 XXX 表示 调用方法的返回值 ,如:Void,Object,等等。(调用静态方法的时候Call后面要加Static

 

详细 映射方法  调用方法 请参考 JNI 文档 ,这个很重要 

 

3、      Java 上层 关键代码

TestProvider.Java 的两个方法

 

package com.duicky;
 
/**
 *
 *
 * @author luxiaofeng <454162034@qq.com>
 *
 */
public class TestProvider {
 
    public static String getTime() {
        LogUtils.printWithSystemOut( "Call From C Java Static Method"   );
        LogUtils.toastMessage(MainActivity.mContext, "Call From C Java Static Method"   );
        return String.valueOf(System.currentTimeMillis());
    }
 
    public void sayHello(String msg) {
        LogUtils.printWithSystemOut("Call From C Java Not Static Method :" + msg);
        LogUtils.toastMessage(MainActivity.mContext, "Call From C Java Not Static Method :" + msg);
    }
 
}

 

 

 

4、      Android.mk 文件 关键代码

LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog
 
 
LOCAL_MODULE    := NDK_04
LOCAL_SRC_FILES := \
CToJava.c \
Provider.c
 
include $(BUILD_SHARED_LIBRARY)

 

老样子,不说了,你懂的。 如果不懂,嘎嘎,那就请点击Android.mk 文件 简介

 

 

5、      JNI文件夹下文件

Provider.h

#include <string.h>
#include <jni.h>
 
void GetTime() ;
void SayHello();

 

 

Provider.c  

#include "Provider.h"
#include <android/log.h>
 
extern JNIEnv* jniEnv;
 
jclass TestProvider;
jobject mTestProvider;
jmethodID getTime;
jmethodID sayHello;
 
int GetProviderInstance(jclass obj_class);
 
/**
 * 初始化 类、对象、方法
 */
int InitProvider() {
 
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitProvider Begin  1" );
 
    if(jniEnv == NULL) {
        return 0;
    }
 
    if(TestProvider == NULL) {
        TestProvider = (*jniEnv)->FindClass(jniEnv,"com/duicky/TestProvider");
        if(TestProvider == NULL){
            return -1;
        }
        __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitProvider Begin  2 ok" );
    }
 
    if (mTestProvider == NULL) {
        if (GetProviderInstance(TestProvider) != 1) {
            (*jniEnv)->DeleteLocalRef(jniEnv, TestProvider);
            return -1;
        }
        __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitProvider Begin  3 ok" );
    }
 
    if (getTime == NULL) {
        getTime = (*jniEnv)->GetStaticMethodID(jniEnv, TestProvider, "getTime","()Ljava/lang/String;");
        if (getTime == NULL) {
            (*jniEnv)->DeleteLocalRef(jniEnv, TestProvider);
            (*jniEnv)->DeleteLocalRef(jniEnv, mTestProvider);
            return -2;
        }
        __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitProvider Begin  4 ok" );
    }
 
    if (sayHello == NULL) {
        sayHello = (*jniEnv)->GetMethodID(jniEnv, TestProvider, "sayHello","(Ljava/lang/String;)V");
        if (sayHello == NULL) {
            (*jniEnv)->DeleteLocalRef(jniEnv, TestProvider);
            (*jniEnv)->DeleteLocalRef(jniEnv, mTestProvider);
            (*jniEnv)->DeleteLocalRef(jniEnv, getTime);
            return -3;
        }
        __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitProvider Begin  5 ok" );
    }
 
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitProvider Begin  6" );
    return 1;
 
}
 
int GetProviderInstance(jclass obj_class) {
 
    if(obj_class == NULL) {
        return 0;
    }
 
    jmethodID construction_id = (*jniEnv)->GetMethodID(jniEnv, obj_class,
            "<init>", "()V");
 
    if (construction_id == 0) {
        return -1;
    }
 
    mTestProvider = (*jniEnv)->NewObject(jniEnv, obj_class,
            construction_id);
 
    if (mTestProvider == NULL) {
        return -2;
    }
 
    return 1;
}
 
/**
 * 获取时间 ---- 调用 Java 方法
 */
void GetTime() {
    if(TestProvider == NULL || getTime == NULL) {
        int result = InitProvider();
        if (result != 1) {
            return;
        }
    }
 
    jstring jstr = NULL;
    char* cstr = NULL;
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "GetTime Begin" );
    jstr = (*jniEnv)->CallStaticObjectMethod(jniEnv, TestProvider, getTime);
    cstr = (char*) (*jniEnv)->GetStringUTFChars(jniEnv,jstr, 0);
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "Success Get Time from Java , Value = %s",cstr );
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "GetTime End" );
 
    (*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, cstr);
    (*jniEnv)->DeleteLocalRef(jniEnv, jstr);
}
 
/**
 * SayHello ---- 调用 Java 方法
 */
void SayHello() {
    if(TestProvider == NULL || mTestProvider == NULL || sayHello == NULL) {
        int result = InitProvider() ;
        if(result != 1) {
            return;
        }
    }
 
    jstring jstrMSG = NULL;
    jstrMSG =(*jniEnv)->NewStringUTF(jniEnv, "Hi,I'm From C");
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "SayHello Begin" );
    (*jniEnv)->CallVoidMethod(jniEnv, mTestProvider, sayHello,jstrMSG);
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "SayHello End" );
 
    (*jniEnv)->DeleteLocalRef(jniEnv, jstrMSG);
}

 

       CToJava.c

      

   

#include <string.h>
#include <android/log.h>
#include <jni.h>
#include "Provider.h"
 
JNIEnv* jniEnv;
 
/**
 *  Java 中 声明的native getTime 方法的实现
 */
void Java_com_duicky_MainActivity_getTime(JNIEnv* env, jobject thiz)
{
 
    if(jniEnv == NULL) {
        jniEnv = env;
    }
 
    GetTime();
}
 
/**
 *  Java 中 声明的native sayHello 方法的实现
 */
void Java_com_duicky_MainActivity_sayHello(JNIEnv* env, jobject thiz)
{
    if (jniEnv == NULL) {
        jniEnv = env;
    }
 
    SayHello();
}

 

 

 

3、运行效果

1、点击 C调用java静态方法”按钮

 

C成功调用了Java中的getTime 方法,通过C方法打印出上层调用得到的时间,并且上层成功吐司出调用信息出来。


 



2
、点击 C调用java非静态方法”按钮

 

C成功调用了sayHello 方法并成功接收到 C 传递的参数,和 吐司出相对应的信息

 



 

4C调用Java注意点

       a) C 映射java 方法时 对应的签名

getTime = (*jniEnv)->GetStaticMethodID(jniEnv, TestProvider, "getTime","()Ljava/lang/String;");

       故事情节还没发展这么快,下一章才会专门介绍下这个签名的使用

       b)映射方法的时候需要区别静态和非静态GetStaticMethodID,GetMethodID

    c)调用的时候也需要区分CallStaticObjectMethod,CallVoidMethod 而且还需要区分返回值类型

 

 

 

有不理解的兄弟请留言,个人技术有限,有讲错的地方请大牛们指出,讲的不够全面的请多多包涵,谢谢,

 

点击下载源码 C调用Java例子


本文出自 duicky 博客 , 转载请注明出处 http://www.cnblogs.com/luxiaofeng54/archive/2011/08/17/2142000.html

分享到:
评论

相关推荐

    JNI反射调用Java方法1

    使用`GetMethodId`函数获取Java方法的ID,这个ID是JNI调用Java方法的关键。函数接受三个参数:JNIEnv指针,类的引用(`jclass`),以及方法名和方法签名的字符串。方法签名描述了方法的参数类型和返回类型,如`"()V...

    LINUX C调用JAVA的静态方法和非静态方法(实例方法)小实例

    在Linux环境中,C语言可以通过Java Native Interface (JNI) 来调用Java的静态和非静态方法,实现两者之间的交互。JNI是Java平台标准的一部分,它允许Java代码和其他语言写的代码进行交互,使得C/C++程序员可以编写...

    JNI中C代码调用使用java属性和方法

    JNI调用Java静态属性的步骤大致如下: 1. 获取Java类对象:和非静态属性类似,使用`GetObjectClass`函数获取目标Java对象所属的类对象。 2. 获取静态字段ID:使用`GetStaticFieldID`函数根据字段名和类型签名获取...

    DELPHI 7 调用 JAVA 接口

    以上步骤详细介绍了如何在Delphi 7中通过JNI调用Java接口,实现两者的交互。这为混合编程提供了可能,允许开发者充分利用两种语言的优点,如Delphi的快速Windows开发和Java的跨平台能力。在实际应用中,可能还需要...

    用JNI实现java和C++的相互调用

    在上述示例中,我们看到`JniTest`类的实例方法和静态方法都被调用了。例如,`jni.PrintHello()`将调用C++中的`Java_JniTest_PrintHello()`,`jni.PrintArray(arr)`则会调用`Java_JniTest_TestArray()`,并将数组`arr...

    JNI开发之javah生成静态和非静态的两个头文件区别代码

    例如,对于一个Java类的实例方法,非静态头文件会定义一个接受`JNIEnv*`和` jobject`参数的函数,`JNIEnv`指针用于调用JNI函数,`jobject`则是对Java对象的引用。 2. **静态头文件(-static)**: 使用`-static`...

    android jni c回调java

    本教程将详细介绍如何在Android中使用JNI实现C语言回调Java的方法,包括有参无参、有无返回值以及静态非静态函数的不同情况。 1. **JNI基础概念** JNI是Java平台的标准组成部分,它提供了一套接口,使得Java代码...

    Qt for Android 用JNI来使C++和Java互调(目前最新版全网只有这个可用)

    这个头文件包含了Java方法的C++声明,使得C++代码能够理解并调用Java方法。 2. **实现JNI函数**:在C++中,我们需要实现这些声明的函数,这些函数将在Android运行时环境中被Java层调用。 3. **注册JNI函数**:在...

    C++调用java代码的JNI实现

    通过上述介绍,我们可以了解到如何在C++环境中通过JNI调用Java代码来实现用户身份验证和权限管理的功能。这种跨语言调用的方法不仅可以提高系统的灵活性,还能充分利用两种语言的优势。对于需要在C++环境中集成Java...

    在C或C++中调用JAVA方法

    总的来说,通过JNI,开发者可以在C/C++代码中无缝地调用Java方法,实现两者的深度融合。然而,这种方式增加了程序的复杂性,同时也可能引入潜在的内存泄漏和线程安全问题,因此在使用时需要谨慎并做好充分的测试。

    java中JNI调用非java(CC++)代码参考.pdf

    在Java中,如果一个方法被声明为`native`,那么这个方法的实现并不在Java代码中,而是通过JNI调用其他语言(如C/C++)的代码来实现。本教程将详细介绍如何在Linux环境下使用JNI调用C/C++动态库。 1. **创建Java类**...

    Jni调用Demo

    JNI接口定义了一组函数和数据类型,使得Java代码能够声明并调用本地方法(即非Java代码),同时本地方法也能调用Java代码。这通常涉及到以下步骤: 1. **编写Java代码**:在Java类中声明native方法,该方法没有具体...

    JNI-Java Native Interface资料(精华)

    JNI的主要职责是提供一套API,使Java代码能够调用非Java语言(如C/C++)编写的本地方法,同时也能让本地代码反向调用Java方法。通过JNI,开发人员可以创建、检查和更新Java对象(包括数组和字符串),调用Java方法,...

    jni编程c回调java的方法

    对于非静态方法,需要获取`thisObj`指向的对象的类并找到对应的方法ID。 ### 6. 链接与编译 将C/C++代码编译为动态链接库(如`libmylibrary.so`)。在Android项目中,这通常通过Android.mk或CMakeLists.txt文件...

    JNI调用C++的应用实例

    《JNI调用C++的应用实例》 JNI,全称Java Native Interface,是Java平台中用于实现Java代码与其他语言(如C/C++)交互的关键技术。自Java 1.1起,JNI已成为Java平台的标准组成部分,它允许Java应用程序利用本地代码...

    jni.rar_JNI编程_java jni_jni_site:www.pudn.com

    JNI提供了多种函数来调用Java的方法,包括静态方法和实例方法。例如,`CallVoidMethod`用于调用返回值为void的方法,`GetObjectField`用于获取对象的字段值。 5. **本地方法的注册** 在C/C++代码中,需要通过`...

    android jni使用java、c c++相互调用

    例如,调用非静态方法: ```c++ jmethodID method = env-&gt;GetMethodID(clazz, "callJavaMethod", "()V"); env-&gt;CallVoidMethod(obj, method); ``` 调用静态方法: ```c++ jmethodID staticMethod = env-&gt;...

    Android Java代码与JNI交互 JNI访问Java类方法 (七)

    - 调用非静态方法:`void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID mid, ...)`。 - 以上函数有对应返回值的版本,例如`CallIntMethod`,`CallLongMethod`等,适用于返回不同类型的方法。 6. **参数和...

    JNI.zip_java jni_jni

    8. **调用Java方法**:本地代码可以通过JNI调用Java方法,包括静态方法、实例方法和构造方法。这涉及到`CallStaticVoidMethod`、`CallVoidMethod`、`NewObject`等函数。 9. **访问Java对象**:JNI允许本地代码访问...

Global site tag (gtag.js) - Google Analytics