Android NDK JNI C++ <5> callback java code & swig
下面我有两个样例,这两个样例在调用上互逆的,一个是功能是在jni中的C/C++语言中实现的,一个是功能用java实现的,但是调用(或者说使用这个功能)是在jni中的C/C++语言实现的(仅仅调用而已),
样例一:jni调用java实现的功能method:
<1> :
java实现的如下:
package nativejni; import android.content.Context; import android.widget.Toast; public class CallNativeFromJni { static{ System.loadLibrary("nativelibs"); } static Context mContext; public CallNativeFromJni(Context ctx){ mContext=ctx; Toast.makeText(mContext, "CallNativeFromJni Construction !", Toast.LENGTH_SHORT).show(); nativeInit(); } public void CallNonStaticMethod(int value){ Toast.makeText(mContext, "non static method : "+value, Toast.LENGTH_SHORT).show(); } public static void CallStaticMethod(int value){ Toast.makeText(mContext, "static method :"+value, Toast.LENGTH_SHORT).show(); } public native void nativeInit(); public native void callNonStaticMethod(); public native void callStaticMethod(); }
上面的代码基本上分成三部分:
第一部分:加载库
static{ System.loadLibrary("nativelibs"); }
第二部分:本地java实现功能部分:
static Context mContext; public CallNativeFromJni(Context ctx){ mContext=ctx; Toast.makeText(mContext, "CallNativeFromJni Construction !", Toast.LENGTH_SHORT).show(); nativeInit(); } public void CallNonStaticMethod(int value){ Toast.makeText(mContext, "non static method : "+value, Toast.LENGTH_SHORT).show(); } public static void CallStaticMethod(int value){ Toast.makeText(mContext, "static method :"+value, Toast.LENGTH_SHORT).show(); }
第三部分:在jni中需要调用的方法名:
public native void nativeInit(); public native void callNonStaticMethod(); public native void callStaticMethod();
第三部分的callNonStaticMethod()等将会调用java代码写CallNonStaticMethod(int value)等方法.
<2> : javah生成头文件以后,
javah -classpath nativejni.CallNativeFromJni
执行上面命令行之前,首先新建jni文件夹,执行后,它会自动在jni文件夹中生成nativejni_CallnativeFromJni.h的头文件,自行修改一下头文件的名字成CallNativeFromJni.h.
<3> : 新建CallNativeFromJni.c文件,编写头文件方法的具体实现:
#include "CallNativeFromJni.h" #include<string.h> jclass mClass; jobject mObject; jmethodID mNonStaticMethodID,mStaticMethodID; JNIEXPORT void JNICALL Java_nativejni_CallNativeFromJni_nativeInit (JNIEnv *env, jobject thiz){ jclass clazz=(*env)->GetObjectClass(env,thiz); mClass=(jclass)(*env)->NewGlobalRef(env,clazz); mObject=(jobject)(*env)->NewGlobalRef(env,thiz); mStaticMethodID=(*env)->GetStaticMethodID(env,mClass,"CallStaticMethod","(I)V"); mNonStaticMethodID=(*env)->GetMethodID(env,mClass,"CallNonStaticMethod","(I)V"); } JNIEXPORT void JNICALL Java_nativejni_CallNativeFromJni_callNonStaticMethod (JNIEnv *env, jobject thiz){ (*env)->CallVoidMethod(env,mObject,mNonStaticMethodID,100); return ; } JNIEXPORT void JNICALL Java_nativejni_CallNativeFromJni_callStaticMethod (JNIEnv *env, jobject thiz){ (*env)->CallVoidMethod(env,mObject,mStaticMethodID,200); return ; }
上面mClass获取方式,还有一种非常常见的:
mClass=(*env)->FindClass(env,"nativejni.CallNativeFromJni"); /* check exception */ if((*env)->ExceptionCheck(env)){ return ;//ERR_FIND_CLASS_FAILED; }
获取后,必须要检查是否成功.
要回调java编写的方法,首先要获得三个字段,jclass,jobject,jmethodID.
API 参考:
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
API样例:
http://www.ibm.com/developerworks/library/j-jni/index.html
jni这一段只能做桥梁连接作用,如果功能使用jni的语法来操作和实现,不是太实际,实际功能实现部分还是用C/C++实现的,可以在这个工程中继续添加fun.c和fun.h两个文件:
fun.h
#ifndef _FUN_HEADER_C__ #define _FUN_HEADER_C__ int addc(int,int); #endif
fun.c
#include "fun.h" int addc(int a,int b){ return a+b; }
让后在上面的CallNativeFromJni.c中添加:
#include "fun.h"
然后在调用本地代码传入参数100改成如下:
(*env)->CallVoidMethod(env,mObject,mNonStaticMethodID,addc(122,1));
即可以了.
当然在Android.mk的LOCAL_SRC_FILES :=字段后面要把所有*.c或者*.cpp的文件包含进来.
<4> 执行ndk-build后,如不出意外,即生成so库文件.
下面介绍通过jni实现功能,java调用,这种有两种方法,一个是从java开始先定义出接口方法名,另外一种是jni先定义出接口,这种方式一般是采用CPlusPlus完成的.
这里面一般采用第二种,这一种直接采用C++和swig生成jni的相关文件方法是最快和最便捷的,不需要去操作j开头的jni开发了,只需要熟悉C++语言即可,查看前面的文章内容即可.

浙公网安备 33010602011771号