/* * 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; }