谈谈关于Android NDK程序使用jni的一些技巧

声明

  欢迎转载,但请保留文章原始出处:) 

    博客园:http://www.cnblogs.com

    kchen http://www.cnblogs.com/kchen/

      新浪微博:http://weibo.com/kchen30 

 

 

在这里,先简单介绍一下Android NDKjni

 

NDK:可以参照~

http://baike.baidu.com/view/5236494.htm

简单来说,NDK就是提供了一个在Android平台上使用c/c++的一个平台,结合IDE,可以轻松快捷的将c/c++源码编译成so文件,并打包进android应用程序的apk里,并提供一堆Android程序特有的库。

 

JNI:可以参照~

http://baike.baidu.com/view/1272329.htm

简单来说,JNI就是允许java代码与其他语言写的代码交互,尤其是为CC++而设计的。

 

开始步骤:可以参照~

ANDROID: NDK编程入门笔记

http://www.cnblogs.com/hibraincol/archive/2011/05/30/2063847.html

搭建好开发环境,并完成hello world之后,就可以开发自己需要的jni应用程序了

 

注:搭建ndk编译环境,有一些问题

Windows平台: 需要安装通过cygwin来模拟linux环境,并且通过linuxgcc来编译

Linux平台:在官网下载好android ndk安装包后,根据帮助一步步安装即可

Mac平台:mac os x虽然是基于unix的,但是默认情况下是不提供开发工具的,也木有gcc 之类的编译工具,开发人员需要先安装xcode以后,才能使用android ndk

 

下面我们说说javac/c++之间调用的问题

Java调用c/c++

 先看例子

 

public class Sample1
{
   
public native int intMethod(int n);
   
public native boolean booleanMethod(boolean bool);
   
public native String stringMethod(String text);
   
public native int intArrayMethod(int[] intArray);

   
public static void main(String[] args)
   {
     System.loadLibrary(
"Sample1");
     Sample1 sample 
= new Sample1();
     
int     square = sample.intMethod(5);
     
boolean bool   = sample.booleanMethod(true);
     String  text   
= sample.stringMethod("JAVA");
     
int     sum    = sample.intArrayMethod(
                         
new int[]{1,1,2,3,5,8,13} );

     System.out.println(
"intMethod: " + square);
     System.out.println(
"booleanMethod: " + bool);
     System.out.println(
"stringMethod: " + text);
     System.out.println(
"intArrayMethod: " + sum);
   }

} 

 

 然后编译,编译完成以后,可以通过javah 工具所生成的 C/C++ 头文件

 

 /* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>
/* Header for class Sample1 */

#ifndef _Included_Sample1
#define _Included_Sample1
#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_Sample1_intMethod
   (JNIEnv 
*, jobject, jint);

 JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
   (JNIEnv 
*, jobject, jboolean);
 
 JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
  (JNIEnv 
*, jobject, jstring);

 JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
  (JNIEnv 
*, jobject, jintArray);
 
 #ifdef __cplusplus
 }
 
#endif
 
#endif

 

 C 函数实现

 #include "Sample1.h"

 #include <string.h>
 
 JNIEXPORT jint JNICALL Java_Sample1_intMethod
   (JNIEnv 
*env, jobject obj, jint num) {
    
return num * num;
 }
 
 JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
   (JNIEnv 
*env, jobject obj, jboolean boolean) {
   
return !boolean;
 }

 JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
   (JNIEnv 
*env, jobject obj, jstring string) {
     
const char *str = (*env)->GetStringUTFChars(env, string0);
     
char cap[128];
     strcpy(cap, str);
     (
*env)->ReleaseStringUTFChars(env, string, str);
     
return (*env)->NewStringUTF(env, strupr(cap));
 }
 
 JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
   (JNIEnv 
*env, jobject obj, jintArray array) {
     
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;
 }
 
 
void main(){}

 

 c++函数实现

 

 #include "Sample1.h"

 #include <string.h>

JNIEXPORT jint JNICALL Java_Sample1_intMethod
  (JNIEnv 
*env, jobject obj, jint num) {
   
return num * num;
 }

 JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
   (JNIEnv 
*env, jobject obj, jboolean boolean) {
   
return !boolean;
 }

 JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
   (JNIEnv 
*env, jobject obj, jstring string) {
     
const char *str = env->GetStringUTFChars(string0);
     
char cap[128];
     strcpy(cap, str);
     env
->ReleaseStringUTFChars(string, str);
     
return env->NewStringUTF(strupr(cap));
 }
 
 JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
   (JNIEnv 
*env, jobject obj, jintArray array) {
     
int i, sum = 0;
     jsize len 
= env->GetArrayLength(array);
     jint 
*body = env->GetIntArrayElements(array, 0);
     
for (i=0; i<len; i++)
     {    sum 
+= body[i];
     }
     env
->ReleaseIntArrayElements(array, body, 0);
     
return sum;
 }

 
void main(){}

 

 

 注:c和c++实现的方式略微不同
C 语法:         jsize len = (*env)->GetArrayLength(env,array);
C++ 语法:       jsize len =env->GetArrayLength(array);

 

 

c/c++调用Java

先看例子
public class Sample2
 {
   
public static int intMethod(int n) {
       
return n*n;
   }

   
public static boolean booleanMethod(boolean bool) {
        
return !bool;
   }
 }

 

 再看c的调用方式

 

 #include <jni.h>


 #ifdef _WIN32
 
#define PATH_SEPARATOR ';'
 
#else
 
#define PATH_SEPARATOR ':'
 
#endif

 
int main()
 {
   JavaVMOption options[
1];
   JNIEnv 
*env;
   JavaVM 
*jvm;
   JavaVMInitArgs vm_args;
   
long status;
   jclass cls;
   jmethodID mid;
   jint square;
   jboolean not;

   options[
0].optionString = "-Djava.class.path=.";
   memset(
&vm_args, 0sizeof(vm_args));
   vm_args.version 
= JNI_VERSION_1_2;
   vm_args.nOptions 
= 1;
   vm_args.options 
= options;
   status 
= JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

   
if (status != JNI_ERR)
   {
     cls 
= (*env)->FindClass(env, "Sample2");
     
if(cls !=0)
     { mid 
= (*env)->GetStaticMethodID(env, cls, "intMethod""(I)I");
       
if(mid !=0)
       { square 
= (*env)->CallStaticIntMethod(env, cls, mid, 5);
                printf(
"Result of intMethod: %d\n", square);
       }

       mid 
= (*env)->GetStaticMethodID(env, cls, "booleanMethod""(Z)Z");
       
if(mid !=0)
      { not 
= (*env)->CallStaticBooleanMethod(env, cls, mid, 1);
         printf(
"Result of booleanMethod: %d\n", not);
       }
     }

     (
*jvm)->DestroyJavaVM(jvm);
     
return 0;
   }
   
else
   
return -1;
 }

 

 再看c++的调用例子

 #include <jni.h>


 #ifdef _WIN32
 
#define PATH_SEPARATOR ';'
 
#else
 
#define PATH_SEPARATOR ':'
 
#endif

 
int main()
 {
      JavaVMOption options[
1];
      JNIEnv 
*env;
      JavaVM 
*jvm;
      JavaVMInitArgs vm_args;
      
long status;
      jclass cls;
      jmethodID mid;
      jint square;
      jboolean not;

      options[
0].optionString = "-Djava.class.path=.";
      memset(
&vm_args, 0sizeof(vm_args));
      vm_args.version 
= JNI_VERSION_1_2;
      vm_args.nOptions 
= 1;
      vm_args.options 
= options;
      status 
= JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

      
if (status != JNI_ERR)
   {
        cls 
= (*env)->FindClass(env, "Sample2");
        
if(cls !=0)
     {   mid 
= (*env)->GetStaticMethodID(env, cls, "intMethod""(I)I");
            
if(mid !=0)
            {  square 
= (*env)->CallStaticIntMethod(env, cls, mid, 5);
               printf(
"Result of intMethod: %d\n", square);
            }

            mid 
= (*env)->GetStaticMethodID(env, cls, "booleanMethod""(Z)Z");
            
if(mid !=0)
            {  not 
= (*env)->CallStaticBooleanMethod(env, cls, mid, 1);
               printf(
"Result of booleanMethod: %d\n", not);
            }
     }

        (
*jvm)->DestroyJavaVM(jvm);
    
return 0;
   }
      
else
        
return -1;
 }

 

C 语法: cls = (*env)->FindClass(env, "Sample2");

C++ 语法: cls = env->FindClass("Sample2");

 

 先简单介绍到这里,下次再说


posted @ 2011-08-03 12:21  kchen  阅读(1703)  评论(1编辑  收藏  举报