转自: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. SpringMVC+BUI实现文件上传(附详解,源码下载)

    中午有限时间写这博文,前言就不必多说了,直奔主题吧. BUI是一个前端框架,关于BUI的介绍请看博主的文章那些年用过的一些前端框架. 下面我们开始实例的讲解! 一.效果演示: 上传成功后,会发现本地相 ...

  2. Dynamics CRM2013 6.1.1.1143版本插件注册器的一个bug

    最近在做的项目客户用的是CRM2013sp1版本,所以插件注册器使用的也是与之对应的6.1.1.1143,悲剧的事情也因此而开始. 在插件中注册step时,工具里有个run in user's con ...

  3. Android 的 Sqlite基本操作

    在 SQL 数据库中保存数据 使用数据库 将数据保存到数据库对于重复或结构化数据(比如契约信息)而言是理想之选. 本课程假定您基本熟悉 SQL 数据库并且可帮助您开始在 Android 中使用 SQL ...

  4. JAVA面向对象-----extends关键字

    继承使用extends关键字实现 1:发现学生是人,工人是人.显然属于is a 的关系,is a就是继承. 2:谁继承谁? 学生继承人,发现学生里的成员变量,姓名和年龄,人里边也都进行了定义.有重 复 ...

  5. Anakia 转换xml文档为其他格式

    一.简介 Anakia 使用JDOM 和Velocity将XML文档转换为特定格式的文档 二.解析xml文档方法 1.DOM java jdk,xml-api.jar 需要加载整个xml文档来构建层次 ...

  6. 【Netty源码分析】Reactor线程模型

    1. 背景 1.1. Java线程模型的演进 1.1.1. 单线程 时间回到十几年前,那时主流的CPU都还是单核(除了商用高性能的小机),CPU的核心频率是机器最重要的指标之一. 在Java领域当时比 ...

  7. 1089. Insert or Merge (25)

    题目如下: According to Wikipedia: Insertion sort iterates, consuming one input element each repetition, ...

  8. 【编程练习】poj1068

    Parencodings Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24202   Accepted: 14201 De ...

  9. iOS隐藏键盘的几种方式

    因为开发中经常要用到textField和textView,在某些情形下隐藏键盘很有必要,而隐藏键盘有多种方式,在合适的场景下用合适的方式隐藏就显得很重要,我也老是记不起来有哪些方法,这里就记录一下,以 ...

  10. nginx+uwsgi+django 部署原理

    python开发群里经常有同学问 nginx+uwsgi+django 着了教程部署,但是不知道他们之间怎么样的关系,于是我就google到了一个让我看起来很认同的图,大家看了也比较认同,于是就分享出 ...