心胸决定格局,眼界决定境界...

android利用JNI调用C++自定义类

找了好久关于android调用C/C++库的文章,但是始终没有一片是关于android利用jni调用C++自定义类的文章,无奈只好看android的源代码,学习android的图形库的实现,因为它的实现底层也是利用C++的skia库。下面就3个文件来描述。


首先是你在java中的一个类,用于你在应用程序中调用这里取名叫Person类

     //如果先有C/C++库,怎么书写java的接口。   如果是类,则java类的最外层接口与C++保持一样,内部调用的native接口就多个类对象指针参数(用int表示)

     如果是纯C库,则一模一样。

[java] view plain copy
 
  1. package whf.jnitest;  
  2.   
  3. public class Person {  
  4.       
  5.     static  
  6.     {  
  7.         System.loadLibrary("Person");  
  8.     }  
  9.       
  10.     private int mNativePerson;  
  11.       
  12.     public Person()  
  13.     {  
  14.         mNativePerson = init();  
  15.     }  
  16.     protected void finalize()  
  17.     {  
  18.         try {  
  19.             finalizer(mNativePerson);  
  20.         } finally {  
  21.             try {  
  22.                 super.finalize();  
  23.             } catch (Throwable e) {  
  24.                 // TODO Auto-generated catch block  
  25.                 e.printStackTrace();  
  26.             }  
  27.         }  
  28.     }     
  29.     public int getAge()  
  30.     {  
  31.         return native_getAge(mNativePerson);  
  32.     }  
  33.       
  34.     public void setAge(int age)  
  35.     {  
  36.         native_setAge(mNativePerson, age);  
  37.     }  
  38.   
  39.     private native void finalizer(int nPerson);  
  40.     public  native int  add(int a, int b);  
  41.     public  native int  sub(int a, int b);  
  42.     private native int  init();  
  43.       
  44.     private native int  native_getAge(int nPerson);  //与类的成员变量有关系,则需要添加指针Int
  45.     private native void native_setAge(int nPerson, int age);  
  46. }  


然后你的C++文件就如下,我定义为CPerson类

 

 

[cpp] view plain copy
 
  1. #define LOG_TAG "this is a first JNI test"  
  2.   
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5. #include <unistd.h>  
  6. #include <sys/types.h>  
  7. #include <sys/stat.h>  
  8. #include <fcntl.h>  
  9. #include <assert.h>  
  10. #include "jni.h"  
  11. #include "CPerson.h"  
  12.   
  13.     //JNI层实现,调用C/C++类实现。     另外也可以将C/C++类写成C接口的函数形式,然后再JNI层函数中直接包含。
  14.    此处的JNI函数,不是由javah直接生成(可以是先生成后,再修改),或者手工直接写,所以后面需要用到注册函数。
  15.   

 

  1.     jint add(JNIEnv *env, jobject obj, jint a, jint b)  
  2.     {  
  3.         return a + b;  
  4.     }  
  5.   
  6.     jint Java_whf_jnitest_Person_sub(JNIEnv *env, jobject obj, jint a, jint b)  
  7.     {  
  8.         return a - b;  
  9.     }  
  10.   
  11.     void Java_whf_jnitest_Person_finalizer(JNIEnv *env, jobject clazz, CPerson *obj)  
  12.     {  
  13.         delete obj;  
  14.     }  
  15.     //private native int  init();   native声明。  如果是javah直接生成,应该类似   jint    Java_whf_jnitest_Person_init(JNIEnv *env, jobject clazz)  
  16.     CPerson * Java_whf_jnitest_Person_init(JNIEnv *env, jobject clazz)  
  17.     {  
  18.         CPerson *p = new CPerson();  
  19.         return p;  
  20.     }  
  21.   
  22.     void Java_whf_jnitest_Person_setAge(JNIEnv *env, jobject clazz, CPerson *obj, jint age)  
  23.     {  
  24.         return obj->setAge(age);  
  25.     }  
  26.   
  27.     jint Java_whf_jnitest_Person_getAge(JNIEnv *env, jobject clazz, CPerson *obj)  
  28.     {  
  29.         return obj->getAge();  
  30.     }  
  31.   
  32.     static JNINativeMethod methods[]{  
  33.         {"add", "(II)I", (void *)add},  
  34.         {"sub", "(II)I", (void *)Java_whf_jnitest_Person_sub},  
  35.         {"finalizer", "(I)V", (void *)Java_whf_jnitest_Person_finalizer},  
  36.         {"init", "()I", (void *)Java_whf_jnitest_Person_init},  
  37.         {"native_setAge", "(II)V", (void *)Java_whf_jnitest_Person_setAge},  
  38.         {"native_getAge", "(I)I", (void *)Java_whf_jnitest_Person_getAge},  
  39.     };  
  40.   
  41.     static const char * classPathName = "whf/jnitest/Person";  
  42.   
  43.     static int registerNativeMethods(JNIEnv* env, const char* className,  
  44.         JNINativeMethod* gMethods, int numMethods)  
  45.     {  
  46.         jclass clazz;  
  47.   
  48.         clazz = env->FindClass(className);  
  49.         if (clazz == NULL) {  
  50.             //LOGE("Native registration unable to find class '%s'", className);  
  51.             return JNI_FALSE;  
  52.         }  
  53.         if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {  
  54.             //LOGE("RegisterNatives failed for '%s'", className);  
  55.             return JNI_FALSE;  
  56.         }  
  57.   
  58.         return JNI_TRUE;  
  59.     }  
  60.   
  61.     static int registerNatives(JNIEnv* env)  
  62.     {  
  63.       if (!registerNativeMethods(env, classPathName,  
  64.                      methods, sizeof(methods) / sizeof(methods[0]))) {  
  65.         return JNI_FALSE;  
  66.       }  
  67.   
  68.       return JNI_TRUE;  
  69.     }  
  70.   
  71.     typedef union {  
  72.         JNIEnv* env;  
  73.         void* venv;  
  74.     } UnionJNIEnvToVoid;  
  75.   
  76.     /* This function will be call when the library first be loaded */  
  77.     jint JNI_OnLoad(JavaVM* vm, void* reserved)  
  78.     {  
  79.         UnionJNIEnvToVoid uenv;  
  80.         JNIEnv* env = NULL;  
  81.         //LOGI("JNI_OnLoad!");  
  82.   
  83.         if (vm->GetEnv((void**)&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {  
  84.             //LOGE("ERROR: GetEnv failed");  
  85.             return -1;  
  86.         }  
  87.   
  88.         env = uenv.env;;  
  89.   
  90.         //jniRegisterNativeMethods(env, "whf/jnitest/Person", methods, sizeof(methods) / sizeof(methods[0]));  
  91.   
  92.         if (registerNatives(env) != JNI_TRUE) {  
  93.             //LOGE("ERROR: registerNatives failed");  
  94.             return -1;  
  95.         }  
  96.   
  97.          return JNI_VERSION_1_4;  
  98.     }  

 

 

CPerson的声明如下:

 

[cpp] view plain copy
 
  1. #ifndef _CPERSON_H_  
  2. #define _CPERSON_H_  
  3.   
  4. class CPerson  
  5. {  
  6. private:  
  7.     int m_age;  
  8. public:  
  9.     CPerson();  
  10.     int getAge();  
  11.     void setAge(int age);  
  12. };  
  13.   
  14. #endif  


这样一个简单的JNI调用C++自定义类就实现了

posted @ 2016-03-03 19:59  WELEN  阅读(530)  评论(0)    收藏  举报