转自:http://www.cnblogs.com/shangdahao/archive/2013/05/02/3053971.html



1、定义native方法并加载动态链接库:

public class HelloJni extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState); TextView tv = new TextView(this);
tv.setText( stringFromJNI() );
setContentView(tv);
} public native String stringFromJNI(); public native String unimplementedStringFromJNI(); static {
System.loadLibrary("hello-jni");
}
}

2、实现native方法:

#include <string.h>
#include <jni.h>
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !"); //in c
return env->NewStringUTF("Hello from JNI !"); //in c++ }

若要定义静态方法:

JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI
(JNIEnv * env, jclass clazz);

头文件可以用javah工具生成:

进入命令行,切换到项目的bin目录下的classes下面,执行 javah -classpath . -jni 包.类名。

或者:cd 到src目录中,执行 javah 包.类名



3、数据

原始数据类型:





引用数据类型:





4、字符窜的操作:

1)新建字符串:

jstring javaString;

javaString = (*env)->NewStringUTF(env, "Hello World!");

2)把java string转换成c string

const jbyte* str;
jboolean isCopy;
str = (*env)->GetStringUTFChars(env, javaString, &isCopy);
if (0 != str) {
printf("Java string: %s", str);
if (JNI_TRUE == isCopy) {
printf("C string is a copy of the Java string.");
} else {
printf("C string points to actual string.");
}
(*env)->ReleaseStringUTFChars(env, javaString, str);

5、数组的操作:

1)新建java数组:

jintArray javaArray;
javaArray = (*env)->NewIntArray(env, 10);
if (0 != javaArray) {
/* You can now use the array. */
}

2)获取数组的值:

jint nativeArray[10];
//将java array 复制到 c array
(*env)->GetIntArrayRegion(env, javaArray, 0, 10, nativeArray);
//将 c array 还原城 java array
(*env)->SetIntArrayRegion(env, javaArray, 0, 10, nativeArray);

获取数组指针:

jint* nativeDirectArray;
jboolean isCopy;
nativeDirectArray = (*env)->GetIntArrayElements(env, javaArray, &isCopy);
//...
(*env)->ReleaseIntArrayElements(env, javaArray, nativeDirectArray, 0);

6、C\C++获取java成员变量

public class JavaClass {
/** Instance field */
private String instanceField = "Instance Field";
/** Static field */
private static String staticField = "Static Field";
...
}

1)获取Field ID

jclass clazz;
clazz = (*env)->GetObjectClass(env, instance); jfieldID instanceFieldId;
instanceFieldId = (*env)->GetFieldID(env, clazz,
"instanceField", "Ljava/lang/String;"); jfieldID staticFieldId;
staticFieldId = (*env)->GetStaticFieldID(env, clazz,
"staticField", "Ljava/lang/String;");

2)获取Static Field

jstring staticField;
staticField = (*env)->GetStaticObjectField(env, clazz, staticFieldId);

7、C\C++调用java函数

public class JavaClass {
/**
* Instance method.
*/
private String instanceMethod() {
return "Instance Method";
}
/**
* Static method.
*/
private static String staticMethod() {
return "Static Method";
}
...
}

1)获取Method ID:

成员函数:

jmethodID instanceMethodId;
instanceMethodId = (*env)->GetMethodID(env, clazz,
"instanceMethod", "()Ljava/lang/String;");

静态函数:

jmethodID staticMethodId;
staticMethodId = (*env)->GetStaticMethodID(env, clazz,
"staticMethod", "()Ljava/lang/String;");

2)调用:

jstring instanceMethodResult;
instanceMethodResult = (*env)->CallStringMethod(env,
instance, instanceMethodId);

变量和函数的描述符:



javap工具可以提取从编译过的class files 中提取这些描述符:

javap –classpath bin/classes –p –s com.example.hellojni.HelloJni

8、处理异常:

public class JavaClass {
/**
* Throwing method.
*/
private void throwingMethod() throws NullPointerException {
   throw new NullPointerException("Null pointer");
}
/**
* Access methods native method.
*/
private native void accessMethods();
}
jthrowable ex;
...
(*env)->CallVoidMethod(env, instance, throwingMethodId);
ex = (*env)->ExceptionOccurred(env);
if (0 != ex) {
(*env)->ExceptionClear(env);
/* Exception handler. */
}

从c\c++抛异常:

jclass clazz;
...
clazz = (*env)->FindClass(env, "java/lang/NullPointerException");
if (0 ! = clazz) {
(*env)->ThrowNew(env, clazz, "Exception message.");
}

9、本地和全局变量:

1)本地变量在函数结束时自动释放内存:

jclass clazz;
clazz = (*env)->FindClass(env, "java/lang/String");

2)新建全局变量:

jclass localClazz;
jclass globalClazz;
...
localClazz = (*env)->FindClass(env, "java/lang/String");
globalClazz = (*env)->NewGlobalRef(env, localClazz);
...
(*env)->DeleteLocalRef(env, localClazz);

3)释放全局变量:

(*env)->DeleteGlobalRef(env, globalClazz);

4)弱全局引用:

弱全局引用可以被内存自动回收:

jclass weakGlobalClazz;
weakGlobalClazz = (*env)->NewWeakGlobalRef(env, localClazz);
if (JNI_FALSE == (*env)->IsSameObject(env, weakGlobalClazz, NULL)) {
/* Object is still live and can be used. */
} else {
/* Object is garbage collected and cannot be used. */
}
(*env)->DeleteWeakGlobalRef(env, weakGlobalClazz);

10、线程:

synchronized(obj) {
/* Synchronized thread-safe code block. */
}
if (JNI_OK == (*env)->MonitorEnter(env, obj)) {
/* Error handling. */
}
/* Synchronized thread-safe code block. */
if (JNI_OK == (*env)->MonitorExit(env, obj)) {
/* Error handling. */
}

native线程不能和java直接通信,必须先绑定到javaVM

JavaVM* cachedJvm;
...
JNIEnv* env;
...
/* Attach the current thread to virtual machine. */
(*cachedJvm)->AttachCurrentThread(cachedJvm, &env, NULL);
/* Thread can communicate with the Java application
using the JNIEnv interface. */
/* Detach the current thread from virtual machine. */
(*cachedJvm)->DetachCurrentThread(cachedJvm);

Android NDK开发三:java和C\C++交互的更多相关文章

  1. Android NDK 开发(四)java传递数据到C【转】

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/41845701 前面几篇文章介绍了Android NDK开发的简单概念.常见错误及处 ...

  2. Android NDK 开发(三)--常见错误锦集合Log的使用【转】

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/41826511  Android NDK开发经常因某些因素会出现一些意想不到的错误, ...

  3. Android NDK开发 JNI操作java构造方法,普通方法,静态方法(七)

    Android NDK开发 JNI操作java普通.静态.构造方法 1.Jni实例化一个Java类的实例jobject 1.通过FindClas( ),获取Java类的的jclass 2.通过GetM ...

  4. Android NDK开发初识

    神秘的Android NDK开发往往众多程序员感到兴奋,但又不知它为何物,由于近期开发应用时,为了是开发的.apk文件不被他人解读(反编译),查阅了很多资料,其中有提到使用NDK开发,怀着好奇的心理, ...

  5. Android NDK开发

    Android NDK 开发教程(极客学院) 一.Android NDK环境搭建 使用最新ndk,直接抛弃cygwin,以前做Android的项目要用到NDK就必须要下载NDK,下载安装Cygwin( ...

  6. android NDK开发环境搭建

    android NDK开发环境搭建 2012-05-14 00:13:58 分类: 嵌入式 基于 Android NDK 的学习之旅-----环境搭建 工欲善其事必先利其器 , 下面介绍下 Eclip ...

  7. !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结

    http://hujiaweibujidao.github.io/blog/2013/11/18/android-ndk-and-opencv-development-3/ Android Ndk a ...

  8. 跟我学Android NDK开发(一)

    Android NDK 开发跟其它开发一样,首先需要配置好开发环境,本文以 Ubuntu系统为例介绍如何进行 Android NDK 开发环境的配置. 1. 简介 什么是 Android NDK 呢? ...

  9. Windows下搭建Android NDK开发环境及命令行编译

    首先说明本文内的相关安装操作参考<Pro Android C++ with the NDK>一书. 安装 Windows搭建Android NDK开发环境需要安装如下部分(同时需要配置对应 ...

随机推荐

  1. The Zen Programmer

    专注 何为专注 关于 休息 怎么睡觉 心无杂念 我的体会 自我分析 初学者心态 无我 不要设置职业目标 敏事慎言 正念 做自己的老板 玩物养志 结语 最近在研读Christian Grobmeier ...

  2. 从1....n中随机输出m个不重复的数

    void knuth(int n, int m) { srand((unsigned) time( NULL)); for (int i = 0; i < n && m; i++ ...

  3. Apache shiro集群实现 (四)shiro授权(Authentication)--访问控制

    Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...

  4. Hibernate之综合问题

    n + 1问题 query.iterate()方式返回迭代查询会开始发出一条语句:查询所有记录ID语句 Hibernate: select student0_.id ascol_0_0_from t_ ...

  5. linux 服务器网络有关的内核参数

    几乎所有的内核模块,包括内核核心模块和驱动程序,都在/proc/sys 文件系统下提供了某些配置文件以提供用户调整模块的属性和行为.通常一个配置文件对应一个内核参数,文件名就是参数的名字,文件的内容是 ...

  6. Android双击退出

    重写返回键 private long tempTime = 0; /** * 双击退出 */ @Override public void onBackPressed() { long firstCli ...

  7. Android必知必会-长按返回健退出

    背景 平常比较常见的都是一定时间间隔内按两次返回键来退出应用,并且第一次点击会有相应的提示,网上资料比较多,这里写一下,长按返回键退出. 实现 实现的方案常用的有两个: 重写dispatchKeyEv ...

  8. 如何正确使用const、static、extern

    转自:http://www.jianshu.com/p/2fd58ed2cf55 前言 本篇文章主要介绍在开发中怎么使用const.static.extern关键字. 一.const 与宏的区别: c ...

  9. ssh用法及命令

    http://blog.csdn.net/pipisorry/article/details/52269785 什么是SSH? 简单说,SSH是一种网络协议,用于计算机之间的加密登录.如果一个用户从本 ...

  10. [Flask]学习杂记--模板

    这个学习杂记主要不是分享经验,更多是记录下falsk的体验过程,以后做东西在深入研究,因为django之前用的时间比较长,所以很多概念都是一看而过,做个试验了解下flask的功能. flask中使用是 ...