android Java与JNI层互相调用
来源:互联网 发布:在线视频转码 知乎 编辑:程序博客网 时间:2024/05/17 03:48
Java层调用JNI中的函数
首先在TextJNI.java层创建一个类TextJNI,类中使用一些native方法
package com.example.androidjni;import android.util.Log;public class TextJNI { static { System.loadLibrary("jniInterface"); } public static int test_jni_getInt() { return getInt(); } public static String test_jni_getString() { return getString(); } public static native int getInt(); public static native String getString(); public static native int nativeCallBack(String str);}
在别的java类中就可以有如下两种形式去调用这边的函数
1、调用TextJNI类中的函数,从而间接调用native方法
TextJNI.test_jni_getInt()
TextJNI.test_jni_getString()
2、直接调用TextJNI类中引用的native方法
TextJNI.nativeCallBack(“ok”)
二、生成对应的.h文件,并在.cpp文件中实现.h文件申明的方法
得到com_example_androidjni_TextJNI.h,然后需要实现com_example_androidjni_TextJNI.cpp如下:
#include "com_example_androidjni_TextJNI.h"#include <stdio.h>#include <stdlib.h>#include "jni.h"int sum(){ int x, y; x = 100; y = 100; x = x + y; return x;}JNIEXPORT jint JNICALL Java_com_example_androidjni_TextJNI_getInt (JNIEnv *, jclass){ return sum();}JNIEXPORT jstring JNICALL Java_com_example_androidjni_TextJNI_getString (JNIEnv *env, jclass){ env->NewStringUTF("HelloNDK");}JNIEXPORT jint JNICALL Java_com_example_androidjni_TextJNI_nativeCallBack (JNIEnv *env, jclass cls, jstring str){ jclass clz = env->FindClass("com/example/androidjni/MainActivity"); jmethodID mid = env->GetMethodID(clz, "callback_func", "(Ljava/lang/String;)I"); jobject obj = env->NewObject(clz, mid); return env->CallIntMethod(obj, mid, str);}
三、编译生成jni库文件.so
具体详细的步骤可以参考:http://blog.csdn.net/luckywang1103/article/details/46958409
JNI层调用Java中的函数
获取类名:
jclass clz = env->FindClass(“com/example/androidjni/MainActivity”);
“”里面是包名+类名,都是以/分隔
jclass clz = env->GetObjectClass(obj);
获取类方法:
jmethodID mid = env->GetMethodID(clz, “callback_func”, “(Ljava/lang/String;)I”);
callback_func是类clz中的函数,()里面的Ljava/lang/String是callback_func函数的参数类型,I是callback_func函数的返回值类型
说明:
1、参数或者返回值为java中的对象时,签名中必须以”L”加上其路径,路径以”/分隔”,最后以”;”结尾
比如说java.lang.String为”Ljava/lang/String;”
2、参数或者返回值为数组类型时,前面加上[
比如[I代表int [],[[D代表double[][]
举个例子:
“(II)V”表示 void func(int, int)
“()Ljava/lang/String;” 表示String func()
“([B)V” 表示func(byte[])
生成类对象:
jobject obj = env->NewObject(jclass clz, jmethodID mid)
调用类成员方法:
env->CallxxxMethod(jobject obj, jmethodID mid, parameters)
类似的有
CallVoidMethod CallStaticVoidMethod
CallIntMethod CallStaticVoidMethod
CallBooleanMethod CallStaticVoidMethod
CallByteMethod CallStaticVoidMethod
操作java的String对象
从java程序中传过去的String对象在本地方法中对应的是jstring类型,jstring类型和c中的char 不同,所以如果直接当作char 使用的话,就会出错。因此在使用之前需要将jstring转换为c/c++中的char *,这里使用JNIEnv提供的方法进行转换。
const char *str = env->GetStringUTFChars(jstr, 0);
env->ReleaseStringUTFChars(jstr, str);
这里使用GetStringUTFChars方法将传进来的prompt(jstring类型)转换成UTF-8的格式,就能在本地方法中使用了。
注意:在使用完你所转换之后的对象之后,需要显示调用ReleaseStringUTFChars方法,让JVM释放转换成UTF-8的string的对象的空间,如果不显示的调用的话,JVM中会一直保存该对象,不会被垃圾回收器回收,因此就会导致内存溢出。
下面是Jni访问String对象的一些方法:
GetStringUTFChars 将jstring转换成为UTF-8格式的char*
GetStringChars 将jstring转换成为Unicode格式的char*
ReleaseStringUTFChars 释放指向UTF-8格式的char*的指针
ReleaseStringChars 释放指向Unicode格式的char*的指针
NewStringUTF 创建一个UTF-8格式的String对象
NewString 创建一个Unicode格式的String对象
GetStringUTFLength 获取UTF-8格式的char*的长度
GetStringLength 获取Unicode格式的char*的长度
下面提供两个String对象和char*互转的方法:
/* c/c++ string turn to java jstring */ jstring charToJstring(JNIEnv* env, const char* pat) { jclass strClass = (*env)->FindClass(env, "java/lang/String"); jmethodID ctorID = (*env)->GetMethodID(env, strClass, "", "([BLjava/lang/String;)V"); jbyteArray bytes = (*env)->NewByteArray(env, strlen(pat)); (*env)->SetByteArrayRegion(env, bytes, 0, strlen(pat), (jbyte*)pat); jstring encoding = (*env)->NewStringUTF(env, "UTF-8"); return (jstring)(*env)->NewObject(env, strClass, ctorID, bytes, encoding); } /* java jstring turn to c/c++ char* */ char* jstringToChar(JNIEnv* env, jstring jstr) { char* pStr = NULL; jclass jstrObj = (*env)->FindClass(env, "java/lang/String"); jstring encode = (*env)->NewStringUTF(env, "utf-8"); jmethodID methodId = (*env)->GetMethodID(env, jstrObj, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray byteArray = (jbyteArray)(*env)->CallObjectMethod(env, jstr, methodId, encode); jsize strLen = (*env)->GetArrayLength(env, byteArray); jbyte *jBuf = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE); if (jBuf > 0) { pStr = (char*)malloc(strLen + 1); if (!pStr) { return NULL; } memcpy(pStr, jBuf, strLen); pStr[strLen] = 0; } env->ReleaseByteArrayElements(byteArray, jBuf, 0); return pStr; }
以上有部分转自:http://zhiweiofli.iteye.com/blog/1830321
举个例子
MainActivity.java
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /* * 1\ Java call function from JNI(nativeCallBack) * 2\ JNI then will call function from java(callback_func) * */ int ret = TextJNI.nativeCallBack("ok"); if (ret == 1) ((TextView)findViewById(R.id.text2)).setText("nativecallback ok");}public int callback_func(String str){ Log.v("va", "hello" + str); return 1;}
TextJNI.java
public class TextJNI { static { System.loadLibrary("jniInterface"); } public static native int nativeCallBack(String str);}
com_example_androidjni_TextJNI.cpp
JNIEXPORT jint JNICALL Java_com_example_androidjni_TextJNI_nativeCallBack (JNIEnv *env, jclass cls, jstring str){ jclass clz = env->FindClass("com/example/androidjni/MainActivity"); jmethodID mid = env->GetMethodID(clz, "callback_func", "(Ljava/lang/String;)I"); jobject obj = env->NewObject(clz, mid); return env->CallIntMethod(obj, mid, str);}
- android Java与JNI层互相调用
- Android之webkit内核JNI层与Java层 函数互相调用方法
- 【转载】Android之webkit内核JNI层与Java层 函数互相调用方法
- android jni中C++与java互相调用小结
- java jni与c++互相调用
- JNI JAVA与C的互相调用
- JNI学习(一)(c和java层对象互相调用)
- cocos2dx 与android函数的互相调用及使用jni
- Android JNI之Java和C互相调用
- Android Jni层调用应用层(Java)的方法
- android与NDK层互相调用类方法
- android之js与java互相调用
- Android Java层与Jni层的数组传递
- JNI--java和C++互相调用
- NativeActivity通过jni调用java层的Android API
- NativeActivity通过jni调用java层的Android API
- Android JNI之JAVA调用C/C++层
- Android JNI实现简单的c层调用Java层函数(C层调用Java层Toast进行提示)
- HDU 1800 Flying to the Mars -- 求一组数中出现频率最大的那个数出现的次数
- 关于it-ebooks.info无法下载的一种解决方法
- DJY-broswer 利用html做桌面应用
- 我的openwrt学习笔记(二十三):MTK7688 elian一键配置原理
- nyoj 44 子串和【最大子串和】
- android Java与JNI层互相调用
- Node.js + MongoDB学习
- LeetCode 题解(195) : Contains Duplicate
- 类Hash结构词典
- 我回来了!
- 白话经典算法系列之七 堆与堆排序
- c#手动创建DataTable
- java static成员变量和成员函数
- springmvc接收页面表单参数