使用JNI在java中调用C代码

来源:互联网 发布:pdf修改软件下载 编辑:程序博客网 时间:2024/05/21 11:25
使用JNI在java中调用C代码
1.定义个类来定义java的native方法
public class DataProvider {
public native int add(int x ,int y);
public native String sayHelloInC(String s);
public native int[] intMethod(int[] iNum); 
  }
2.用javah编译那个native的类.
3.新建jni的文件夹.把刚刚编译生成的.h的头文件给拷贝进来.
4.在jni的文件夹下新建XX.c文件
5.编写c代码
#include<stdio.h>
#include"com_mccxxiv_ndk3_DataProvider.h"
#include <android/log.h>
#include<jni.h>
#include<malloc.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
//工具方法 : 把java中的string 转化成 c语言中 char数组
//返回值是 char数组的首地址
char*   Jstring2CStr(JNIEnv*   env,   jstring   jstr)
{
 char*   rtn   =   NULL;
 jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String");
 jstring   strencode   =   (*env)->NewStringUTF(env,"GB2312");
 jmethodID   mid   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B");
 jbyteArray   barr=   (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");
 jsize   alen   =   (*env)->GetArrayLength(env,barr);
 jbyte*   ba   =   (*env)->GetByteArrayElements(env,barr,JNI_FALSE);
 if(alen   >   0)
 {
  rtn   =   (char*)malloc(alen+1);         //"\0"
  memcpy(rtn,ba,alen);
  rtn[alen]=0;
 }
 (*env)->ReleaseByteArrayElements(env,barr,ba,0);  //释放空间
 return rtn;
}


JNIEXPORT jint JNICALL Java_com_mccxxiv_ndk3_DataProvider_add
  (JNIEnv * env, jobject obj, jint x, jint y){
LOGI("x= %d",x);
LOGI("y= %d",y);
return x+y;
}


JNIEXPORT jstring JNICALL Java_com_mccxxiv_ndk3_DataProvider_sayHelloInC
  (JNIEnv * env, jobject obj, jstring jstr){
 char* p = Jstring2CStr(env,jstr); // 返回的是char数组的首地址
 // 在c语言中 打印 java传递过来的字符串
 LOGI("in c code = %s",p);

 char* newstr="nihao ";

     //strcat string cat(dest,source);  strcat(newstr,p);
 // 要求目标的 内存空间 可以存放 拼装后的字符串的大小
  //strcat(newstr,p) 该函数是把两个字符串连接起来
     return (*env)->NewStringUTF(env,strcat(p,newstr)); //该函数是把c的字符串转换成jstring
}


JNIEXPORT jintArray JNICALL Java_com_mccxxiv_ndk3_DataProvider_intMethod
  (JNIEnv * env, jobject obj, jintArray jintarr){
int len = (*env)->GetArrayLength(env,jintarr);//获取java数组的长度
LOGI("len = %d",len);
LOGI("dizhi = %#x",&jintarr);
jint* arr = (*env)->GetIntArrayElements(env,jintarr,0);//获取数组中的每个元素.0是指不使用拷贝.1是指使用拷贝.
int i =0;
int temp;
for(;i<len;i++){
LOGI("arr[%d] = %d",i, *(arr+i));
//*(arr+i) +=10;
temp = *(arr+i) + 10;//修改数组中的值
(*env)->SetIntArrayRegion(env,jintarr,i,1,&temp);//操作数组里面的元素

}
(*env)->ReleaseIntArrayElements(env,jintarr,arr,0); //释放内存空间
return jintarr;
}
6.在jni文件夹下新建Android.mk文件
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS) #类似于工具初始化的操作 

LOCAL_MODULE    := Hello
LOCAL_SRC_FILES := Hello.c

LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY) 
7.用ndk-build命令编译
8.在主Activity中调用native方法
public class MainActivity extends Activity {
 //静态代码块是加载编译生成的c的动态库文件
static{
System.loadLibrary("Hello");
}

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    
    public void passInt(View view){
    DataProvider provider = new DataProvider();
    int result = provider.add(3, 5);
    Toast.makeText(this, "相加的结果是: "+ result, 1).show();
    }
    
    public void passsString(View view){
    DataProvider provider = new DataProvider();
    String result = provider.sayHelloInC("zhang san");
    Toast.makeText(this,  result, 1).show();
    }
    
    public void passsIntArr(View view){
    int[] arr ={1,2,3,4,5};
    System.out.println(arr.toString());
    DataProvider provider = new DataProvider();
    int[] result =  provider.intMethod(arr);
    
    for(int i =0;i<result.length;i++){
    System.out.println("java result["+i+"]=" +result[i]);
    }
    }
}

原创粉丝点击