android ndk 基数排序

由于工作需要需要了解一下android的ndk开发,就做了一个简单的例子。

环境jdk1.6,ndk=android-ndk-r8-windows,eclips3.7,androidsdk=10

功能:android的调用一个c99写的基数排序方法

工程结构:

内容: 红色部分都是重点

  1. package com.example.hellojin;
  2. import android.annotation.SuppressLint;
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.view.Menu;
  6. import android.widget.TextView;
  7. public class HelloJin extends Activity {
  8.     @Override
  9.     public void onCreate(Bundle savedInstanceState) {
  10.         super.onCreate(savedInstanceState);
  11.         TextView  tv = new TextView(this);
  12.         int[] data={3, 22, 93, 43, 55, 14, 28, 64, 88, 81};
  13.         //"排序之前的数值:";
  14.         StringBuffer stringBuffer=new StringBuffer("排序之前的数值\r\n");
  15.         for(int i=0;i<10;i++){
  16.             stringBuffer.append(data[i]+",");
  17.         }
  18.        
  19.         radixSort(data,10);
  20.         stringBuffer.append("排序之后的数值:\r\n");
  21.         for(int i=0;i<10;i++)
  22.             stringBuffer.append(data[i]+",");
  23.         tv.setText( stringFromJNI()+stringBuffer );
  24.         setContentView(tv);
  25.       //  setContentView(R.layout.activity_hello_jin);
  26.     }
  27.    
  28.     public native String stringFromJNI();
  29.    
  30.     public native void notStringFromJNI();
  31.     //基数排序
  32.     public native void radixSort(int[] array ,int maxLength);
  33.     @Override
  34.     public boolean onCreateOptionsMenu(Menu menu) {
  35.         getMenuInflater().inflate(R.menu.activity_hello_jin, menu);
  36.         return true;
  37.     }
  38.     static {
  39.         System.loadLibrary("hello-jni");
  40.     }
  41. }

编译一下目的生成HelloJin.clas字节码文件,我的的工程在D:\lyl_android\所以字节码文件的绝对路径在

D:\lyl_android\HelloJin\bin\classes\com\example\hellojin目录下面

假使我们已经配置好了jdk,ndk环境,(这个可以配好后用相应的命令验证一下看javah和ndk-build是否可以用)

我们在我们的工程目录下建立一个名字叫jni的目录(即D:\lyl_android\HelloJin\jni)用来存放我的本地化代码和

makefile文件Android.mk(如果想详细知道makefile是什么,可以看看linux)。

现在我们来生成我们本地化的JNI的头文件,JNI命名规则手动拼写容易出错,我们借助JAVAH命令

cmd:打开命令行

D:切换盘符

cd D:\lyl_android\hellojin 进入工程目录

javah -classpath bin\classess -d jni com.example.hellojin.HelloJin

这个命令的解释为:在本工程下bin\classes 目录下面.class文件中寻找类全名为com.example.hellojin.HelloJin的类,运行

javah命令生成java本地化的C头文件com_example_hellojin_HelloJin.h存放在工程目录下的jni目录(D:\lyl_android\HelloJin\jni)下。

com_example_hellojin_HelloJin.h的内容:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_hellojin_HelloJin */

#ifndef _Included_com_example_hellojin_HelloJin
#define _Included_com_example_hellojin_HelloJin
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_hellojin_HelloJin
 * Method:    stringFromJNI
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_hellojin_HelloJin_stringFromJNI
  (JNIEnv *, jobject);

/*
 * Class:     com_example_hellojin_HelloJin
 * Method:    notStringFromJNI
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_hellojin_HelloJin_notStringFromJNI
  (JNIEnv *, jobject);

/*
 * Class:     com_example_hellojin_HelloJin
 * Method:    radixSort
 * Signature: ([II)V
 */
JNIEXPORT void JNICALL Java_com_example_hellojin_HelloJin_radixSort
  (JNIEnv *, jobject, jintArray, jint);

#ifdef __cplusplus
}
#endif
#endif

建立一个hello-jni.c的文件,实现com_example_hellojin_HelloJin.h的方法如下所示:

#include <string.h>
#include <jni.h>


/* This is a trivial JNI example where we use a native method
 * to return a new VM String. See the corresponding Java source
 * file located at:
 *
 *   apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java
 */


JNIEXPORT jstring JNICALL Java_com_example_hellojin_HelloJin_stringFromJNI
  (JNIEnv * env, jobject jb){
      return (*env)->NewStringUTF(env, "Hello from JNI !");
  }

/*
 * Class:     com_example_hellojin_HelloJin
 * Method:    notStringFromJNI
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_hellojin_HelloJin_notStringFromJNI
  (JNIEnv *env, jobject jb){
      return ;
  }


int data[10]={73, 22, 93, 43, 55, 14, 28, 65, 39, 81};  //待排序的数组
typedef struct list  //静态链表结构体类型
{
    int data;
    int next;
}List;
List bucket[10];   //构造十个桶
List d[10];        //将待排序数据构造成list类型的数组
int maxbit(int data[],int n)   //计算待排序数组元数的最长的位数
{
    int d=1;
    int i=0;
    for(;i<n;i++)
    {
        int c=1;
        int p=data[i];
        while(p/10)
        {
            p=p/10;
            c++;
        }
        if(c>d)
            d=c;
    }
    return d;
}
void init(int data[],int n)  //清桶的过程,以及将临时的数组放到d【10】数组中
{
       int j=0;
        for(j=0;j<n;j++)
        {
            bucket[j].next=-1;
            bucket[j].data=j;
        }
        for(j=0;j<n;j++)
        {
          d[j].data=data[j];
          d[j].next=-1;
        }
}
void RadioSort(int data[],int n)   //基数排序的过程
{
   
    int p=maxbit(data,n);   //先求出最长的位数
    int r=1;
    int i=0;
    for(;i<p;i++)   //执行装桶倒桶的次数
    {
        init(data,n);   //复位清桶的过程
        if(i!=0)   //第一次装桶的时候从小到大开始装,之后都从大到小装桶
        {   int k=n-1;
            for(;k>=0;k--)
            {
                int a=d[k].data/r;
                int b=a%10;
                d[k].next=bucket[b].next;
                bucket[b].next=k;
            }
        }
        else
        {   int k=0;
            for(;k<n;k++)
            {
                int a=d[k].data/r;
                int b=a%10;
                d[k].next=bucket[b].next;
                bucket[b].next=k;
            }
        }
       
        int c=0;
        int k=0;
        for(;k<n;k++)   //倒桶的过程,将其放到data数组当中
        {   
           
            if(bucket[k].next!=-1)
            {
                int p=bucket[k].next;
                data[c++]=d[p].data;
                while(d[p].next!=-1){
                        data[c++]=d[d[p].next].data;
                        p=d[p].next;
                }
            }
        }
        r=r*10;  //为了后面对十位数以及高位求当前位置上的数字
    }
}
JNIEXPORT void JNICALL Java_com_example_hellojin_HelloJin_radixSort
  (JNIEnv * env, jobject jb, jintArray data, jint maxlen){
     
    int size = (*env)->GetArrayLength(env, data);

          jint i;
        //  (*env)->GetIntArrayRegion(data, 0, 10, buf);

        jint *buf = (*env)->GetIntArrayElements(env, data, 0 );
        RadioSort(buf,size);

        /*  for (i = 0; i < 10; i++) {
              printf("%u",buf[i]);
          }*/
     (*env)->ReleaseIntArrayElements(env, data, buf, 0);
          //env->SetIntArrayRegion(data, 0, 10, buf);

      return;
     
  }

在hello-jni.c文件同级目录中(D:\lyl_android\HelloJin\jni)建立一个名为Android.mk的文件内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)

这个MK文件的具体含义可以看android ndk文档,我们需要改动的地方就包括

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

就可以了

好现在准备工作已经做好,在cmd下D:\lyl_android\HelloJin目录下运行命令ndk-build

大功告成,通过eclipse重新编译android项目搞定;


你可能感兴趣的:(jni,NDK,基数排序,jni传值)