在写android程序的时候会用到jni,接下来的代码讲诉C实现,环境配置请看我其他的博客,不多说,直接上代码,代码上几乎每一句都会解释,绝对易懂
#include "com_ndk_test_JniClient.h"
#include <stdlib.h>
//#include<jni.h>
#include <stdio.h>
#define ARRAY_LENGTH 5//宏定义
#ifdef __cplusplus
extern "C"
{
#endif
/*
* Class: com_ndk_test_JniClient
* Method: AddStr
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ndk_test_JniClient_AddStr(JNIEnv *env,
jclass arg, jstring a, jstring b) {
//JNIEnv也是在jni.h中定义的,代表JNI调用的上下文,
//GetStringUTFChars()、ReleaseStringUTFChars()和NewStringUTF()均是JNIEnv的函数。
//jstring str = (*env)->NewStringUTF(env, "HelloWorld from JNI !");
//从JNI调用上下文中获取UTF编码的输入字符,将其放在指针str所指向 的一段内存中
const char* str = (*env)->GetStringUTFChars(env, a, 0); //这是c的写法,接下来没有注释的都是有c编写
//const char* s1 = env->GetStringUTFChars(a, 0);//这是c++的写法,以下的方法都是这种形式
char cap[128]; //定义char数组
strcpy(cap, str); //复制字符串到cap
(*env)->ReleaseStringUTFChars(env, a, str); //释放这段内存,个人认为这个像c++虚函数
int i = 0;
for (i = 0; i < strlen(cap); i++)
*(cap + i) = (char) toupper(*(cap + i)); //将经过大写转换的字符串予以返回
return (*env)->NewStringUTF(env, cap); //C语言的字符串指针 转换为JNI的jstring类型
// return (*env)->NewStringUTF(env, strupr(cap));
// return str;
}
/*
* Class: com_ndk_test_JniClient
* Method: AddInt
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_ndk_test_JniClient_AddInt(JNIEnv *env,
jclass arg, jint a, jint b) {
return a + b;
}
;
//TODO
JNIEXPORT jint JNICALL Java_com_ndk_test_JniClient_intArrayMethord(JNIEnv * env,
jclass clazz, jintArray array) {
// return 200;
int i, sum = 0;
jsize len = (*env)->GetArrayLength(env, array);
jint *body = (*env)->GetIntArrayElements(env, array, 0);
for (i = 0; i < len; i++) {
sum += body[i];
}
(*env)->ReleaseIntArrayElements(env, array, body, 0);
return sum;
}
JNIEXPORT jboolean JNICALL Java_com_ndk_test_JniClient_booleanMethord(
JNIEnv *env, jclass clazz, jboolean b) {
return b;
}
/**
*
* 以下代码需要在java程序中声明,头文件中也没有改写
* */
JNIEXPORT jintArray JNICALL Java_com_ndk_test_JniClient_intMethord(JNIEnv *env,
jclass clazz) {
int i = 1; //jint是在JNI框 架内特有的整数类型
jintArray array; //定义数组对象
array = (*env)->NewIntArray(env, 10); //开辟出一个长度为10 的jint数组
for (; i <= 10; i++) //依次向该数组中放入元素1-10
(*env)->SetIntArrayRegion(env, array, i - 1, 1, &i);
//演示GetArrayLength() 和GetIntArrayElements()这两个函数的使用方法
/* 获取数组对象的元素个数 */
int len = (*env)->GetArrayLength(env, array);
/* 获取数组中的所有元素 */
jint* elems = (*env)->GetIntArrayElements(env, array, 0);
for (i = 0; i < len; i++)
printf("ELEMENT %d IS %d/n", i, elems[i]);
return array;
}
/**
* 所有的本地方法的第一个参数都是指向JNIEnv结构的。
* 这个结构是用来调用JNI函数的。第二个参数jclass的意义,
* 要看方法是不是静态的(static)或者实例(Instance)的。
* 前者,jclass代表一个类对象的引用,而后者是被调用的方法所属对象的引用。
* 深化:虽然仍然是传递数组,但是数组的基类换成了字符串这样一种对象数据类型。
* Java程序将向C程序传入一个包含中文字符的字符串,
* C程序并没有处理这个字符串,而是开辟出一个新的字符串数组返回给Java程序,其中还包含两个汉字字符串。
* java写法----->: public native String[] stringMethod(String text);
public static void main(String[] args)
throws java.io.UnsupportedEncodingException
{
System.loadLibrary("Sample3");
Sample3 sample = new Sample3();
String[] texts = sample.stringMethod("java编程思想");
for(int i=0;i<texts.length;i++)
{
texts[i]=new String(texts[i].getBytes("ISO8859-1"),"GBK");
System.out.print( texts[i] );
}
System.out.println();
}
* */
JNIEXPORT jobjectArray JNICALL Java_com_ndk_test_JniClient_stringMethord(
JNIEnv *env, jclass obj, jstring string) {
//通过FindClass()函数在JNI上下文中获取到java.lang.String的类型 (Class),并将其赋予jclass变量
jclass objClass = (*env)->FindClass(env, "java/lang/String");
//JNI框架并 没有定义专门的字符串数组,
//而是使用jobjectArray——对象数组,
//对象数组的基类是jclass,jclass是JNI框架内特有的类型,
//相当 于Java语言中的Class类型
//定义了一个长度为5的对象数组texts
jobjectArray texts = (*env)->NewObjectArray(env, (jsize) ARRAY_LENGTH,
objClass, 0);
jstring jstr;
char* sa[] = { "Hello,", "world!", "JNI", "很", "好玩" };
int i = 0;
//循环放入预先定义好的sa数组中的字符串,
//当然前置条件是使用NewStringUTF()函数将C语言的字符串转换为jstring类型
for (; i < ARRAY_LENGTH; i++) {
jstr = (*env)->NewStringUTF(env, sa[i]);
(*env)->SetObjectArrayElement(env, texts, i, jstr); //必须放入jstring
}
//中文字符则是用支持GBK的输入法输入的,而Java程序采用 ISO8859_1字符集存放JNI调用的返回字符
return texts;
}
/**
* 演示的是C程序向Java程序传递对象数组,
* 而且对象数组中存放的不再是字符串,
* 而是一个在Java中自定义的、含有一个topic属性的MailInfo对象类型
*MailInfo对象定义如下:->
public class MailInfo {
public String topic;
public String getTopic()
{
return this.topic;
}
public void setTopic(String topic)
{
this.topic=topic;
}
}
Java程序的源代码如下:->
public class Sample4
{
public native MailInfo[] objectMethod(String text);
public static void main(String[] args)
{
System.loadLibrary("Sample4");
Sample4 sample = new Sample4();
MailInfo[] mails = sample.objectMethod("Thinking In Java");
for(int i=0;i<mails.length;i++)
System.out.println(mails[i].topic);
}
}
* */
JNIEXPORT jboolean JNICALL Java_com_ndk_test_JniClient_objectMethod(JNIEnv *env,
jobject obj, jstring string) {
//这次通过FindClass()函数在JNI上下文中获取的是java.lang.Object的类型(Class),
//并将 其作为基类开辟出一个长度为5的对象数组( #define ARRAY_LENGTH 5),准备用来存放MailInfo对象。
class objClass = (*env)->FindClass(env, "java/lang/Object");
jobjectArray mails = (*env)->NewObjectArray(env, (jsize) ARRAY_LENGTH,
objClass, 0);
jclass objectClass = (*env)->FindClass(env, "MailInfo");
//创建一个jfieldID类型的变量,在JNI中,操作对 象属性都是通过jfieldID进行的.
//首先查找得到MailInfo的类型(Class),
//然后基于这个jclass进一步获取其名为 topic的属性,并将其赋予jfieldID变量。
jfieldID topicFieldId = (*env)->GetFieldID(env, objectClass, "topic",
"Ljava/lang/String;");
int i = 0;
//循环向对象数组中放入jobject对象。 SetObjectField()函数属于首次使用,
//该函数的作用是向jobject的属性赋值,而值的内容正是Java程序传入的jstring变量 值。
//请注意在向对象属性赋值和向对象数组中放入对象的过程中,
//我们使用了在函数头部分定义的jobject类型的环境参数obj作为中介。
//至此,JNI框 架固有的两个环境入参env和obj,我们都有涉及。
for (; i < ARRAY_LENGTH; i++) {
(*env)->SetObjectField(env, obj, topicFieldId, string);
(*env)->SetObjectArrayElement(env, mails, i, obj);
}
return mails;
}
#ifdef __cplusplus
}
#endif
package com.ndk.test;
public class JniClient {
static {
System.loadLibrary("TestNdk");
}
private JniClient() {
}
private static JniClient jniClient = new JniClient();
public static JniClient getInstance() {
return jniClient;
}
public native String AddStr(String strA, String strB);
public native int AddInt(int a, int b);
// ==============
public native int intArrayMethord(int[] intArray);
public native boolean booleanMethord(boolean b);
}
编写android程序调用jni本地方法的实现(详细例子),布布扣,bubuko.com
原文:http://blog.csdn.net/u012083681/article/details/23043085