jni

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "simplejni_NativeAdd.cpp"
#include <utils/Log.h>
#include <stdio.h>
#include "jni.h"

static const char *classPathName = "com/archermind/teast/NativeNadd";

char* jstringTostring(JNIEnv* env, jstring jstr);
jstring stoJstring(JNIEnv* env, const char* pat);

static jboolean
getjboolean(JNIEnv *env, jobject thiz, jboolean z){
	return !z;
}

static jbyte
getjbyte(JNIEnv *env, jobject thiz, jbyte b){
	LOGD("%s=%d","getbyte",b);
	return b+1;
}

static jchar
getjchar(JNIEnv *env, jobject thiz, jchar c){
	LOGD("%s=%d","getchar",c);
	return c+1;
}

static jshort
getjshort(JNIEnv *env, jobject thiz, jshort s){
	LOGD("%s=%d","getshort",s);
	return s+1;
}

static jint
getjint(JNIEnv *env, jobject thiz, jint i){
	LOGD("%s=%d","getint",i);
    	jclass clazz;
    	jmethodID methodID;
    	clazz = env->FindClass(classPathName);
    	if (clazz != NULL) {
		/*java callback,call from c/c++ to java */
		methodID = env->GetMethodID(clazz, "javaAdd", "(II)I");
		int ret = env->CallIntMethod(thiz, methodID, i, i);
		LOGD("ret=%d",ret);
		return ret;
    	}
	return i+1;
}

static jfloat
getjfloat(JNIEnv *env, jobject thiz, jfloat f){
	LOGD("%s=%f","getfloat",f);
	return f+1;
}

static jdouble
getjdouble(JNIEnv *env, jobject thiz, jdouble d){
	LOGD("%s=%f","getdouble",d);
	return d+1;
}

static jlong
getjlong(JNIEnv *env, jobject thiz, jlong j){
	LOGD("%s=%d","getlong",(int)j);
	return j+1;
}

static jobject
getobjdata(JNIEnv *env, jobject thiz, jobject obj){
	jclass clazz =(env)->FindClass("com/archermind/teast/ObjData");

	//从传进来的对象中取出byte[],对应jbyteArray类型
	jfieldID byteData = (env)->GetFieldID(clazz,"bData","[B");
	jbyteArray pDataIn = (jbyteArray) (env)->GetObjectField(obj, byteData);
	jsize theArrayLeng = env->GetArrayLength(pDataIn);
	//jbyteArrya转为jbyte*
	jbyte *arrayBody = env->GetByteArrayElements(pDataIn,0);
        //jbyte*转为char*
	char *jDataIn = (char *)arrayBody;
	*jDataIn=*jDataIn+1;

	//从传进来的对象中取出int
	jfieldID intData = (env)->GetFieldID(clazz,"len","I");
	jint jintdata = (jint) (env)->GetObjectField(obj, intData);
	jintdata = jintdata + 1;	
	LOGD("jindata=%d",jintdata);

	//从传进来的对象中取出StringArray
	jfieldID strsData = (env)->GetFieldID(clazz,"strs","[Ljava/lang/String;");
	jobjectArray jstrArraydata = (jobjectArray) (env)->GetObjectField(obj, strsData);
	jsize thestrArrayLen = env->GetArrayLength(jstrArraydata);
	int i = 0;   
	for (i = 0; i < thestrArrayLen; i++) {   
		jobject obj = (env)->GetObjectArrayElement(jstrArraydata, i);   
		jstring str = (jstring)obj;   
		char* szStr = jstringTostring(env,str);
		printf(" %d-%s ", i, szStr);   
		free(szStr);
	}


	//将char*转为jbyte*
	char *jDataOut = jDataIn;
	jbyte *bytes = (jbyte*)jDataOut;   
	//将jbyte*转为jbyteArray
	jbyteArray jarray = env->NewByteArray(theArrayLeng);
	env->SetByteArrayRegion(jarray, 0, theArrayLeng, bytes);

	//创建jobjectArray
	jobjectArray jretargs = 0;   
	jsize sizeofstrArray = 5;   
	jclass objClass = (env)->FindClass("java/lang/String");   
	jretargs = (env)->NewObjectArray(sizeofstrArray, objClass, 0);   
	//给jobjectArray赋值
	jstring strTmp;   
	const char* sa[] = { "Hello", "world", "zhang", "san", "yuang" };   
	int j = 0;   
	for (j = 0; j < sizeofstrArray; j++) {   
		strTmp = stoJstring(env,sa[j]);
		(env)->SetObjectArrayElement(jretargs, j, strTmp);   
	}   

	//给每一个实例的变量赋值
	(env)->SetObjectField(obj,byteData,jarray);
	(env)->SetIntField(obj,intData,jintdata);
	(env)->SetObjectField(obj,strsData,jretargs);

	//release
	(env)->ReleaseByteArrayElements(pDataIn, arrayBody, 0); 	
	
	return obj;
}

static jstring
getjstring(JNIEnv *env, jobject thiz, jstring jstr){
	char *str = jstringTostring(env,jstr);
	LOGD("%s=%s","getstring",str);
	const char *temp ="_sss";
	int len = strlen(str) + strlen(temp) +1 ;
	char *str3 = new char[len];
	strcpy(str3,str);
	strcat(str3,temp);
	sprintf(str3,"%s%s",str,temp);
	jstring js = stoJstring(env,str3);
	delete[] str3;
	free(str);	
	return js;
}

// jstring to char*
char* jstringTostring(JNIEnv* env, jstring jstr)
{
	char* rtn = NULL;
	jclass clsstring = env->FindClass("java/lang/String");
	jstring strencode = env->NewStringUTF("utf-8");
	jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
	jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
	jsize alen = env->GetArrayLength(barr);
	jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
	if (alen > 0)
	{
		rtn = (char*)malloc(alen + 1);
		memcpy(rtn, ba, alen);
		rtn[alen] = 0;
	}
	env->ReleaseByteArrayElements(barr, ba, 0);
	return rtn;
} 

//char* to jstring
jstring stoJstring(JNIEnv* env, const char* pat)
{
	jclass strClass = env->FindClass("java/lang/String");
	jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
	jbyteArray bytes = env->NewByteArray(strlen(pat));
	env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);
	jstring encoding = env->NewStringUTF("utf-8");
	return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
} 

static JNINativeMethod methods[] = {
  {"getBoolean", "(Z)Z", (void*)getjboolean },
  {"getByte", "(B)B", (void*)getjbyte },
  {"getChar", "(C)C", (void*)getjchar },
  {"getShort", "(S)S", (void*)getjshort },
  {"getInt", "(I)I", (void*)getjint },
  {"getFloat", "(F)F", (void*)getjfloat },
  {"getDouble", "(D)D", (void*)getjdouble },
  {"getLong", "(J)J", (void*)getjlong },
  {"getString", "(Ljava/lang/String;)Ljava/lang/String;", (void*)getjstring },
  {"getObjData", "(Lcom/archermind/teast/ObjData;)Lcom/archermind/teast/ObjData;", (void*)getobjdata },

};

/*
 * Register several native methods for one class.
 */
static int registerNativeMethods(JNIEnv* env, const char* className,
    JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;

    clazz = env->FindClass(className);
    if (clazz == NULL) {
        LOGE("Native registration unable to find class '%s'", className);
        return JNI_FALSE;
    }
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        LOGE("RegisterNatives failed for '%s'", className);
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

/*
 * Register native methods for all classes we know about.
 *
 * returns JNI_TRUE on success.
 */
static int registerNatives(JNIEnv* env)
{
  if (!registerNativeMethods(env, classPathName,
                 methods, sizeof(methods) / sizeof(methods[0]))) {
    return JNI_FALSE;
  }

  return JNI_TRUE;
}


// ----------------------------------------------------------------------------

/*
 * This is called by the VM when the shared library is first loaded.
 */
 
typedef union {
    JNIEnv* env;
    void* venv;
} UnionJNIEnvToVoid;

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    UnionJNIEnvToVoid uenv;
    uenv.venv = NULL;
    jint result = -1;
    JNIEnv* env = NULL;
    
    LOGI("JNI_OnLoad");

    if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
        LOGE("ERROR: GetEnv failed");
        goto bail;
    }
    env = uenv.env;

    if (registerNatives(env) != JNI_TRUE) {
        LOGE("ERROR: registerNatives failed");
        goto bail;
    }
    
    result = JNI_VERSION_1_4;
    
bail:
    return result;
}


package com.archermind.teast;

import android.util.Log;
/*
Z boolean
B byte
C char
S short
I int
J long
F float
D double
Ljava/lang/String String;
*/

/*
jboolean,
jbyte,
jchar,
jshort,
jint,
jlong,
jfloat,
jdouble
jstring
*/
public class NativeNadd {

    static {

        System.loadLibrary("teastjni");
        
    }
    public native boolean getBoolean(boolean b);
    public native byte getByte(byte b);   
    public native char getChar(char b);   
    public native short getShort(short b);   
    public native int getInt(int b);    
    public native float getFloat(float f);   
    public native double getDouble(double d);   
    public native long getLong(long b);        
    public native String getString(String str);   
//    public native String[] getStringArray(String[] sa);   

    public native ObjData getObjData(ObjData obj);
    	
    private int javaAdd(int a, int b){
    	Log.i("xx","javaAdd");
    	return a + b + 1 ;
    }
    
}
class ObjData { 
	public byte[]  bData;
	public int len;      
	public String[] strs;
}

你可能感兴趣的:(jni)