java中通过ndk调用c/c++ 例子,详细解释

        上篇文章中已经介绍了,关于NDK开发环境的搭建,这里不做赘述。这篇文章主要是通过一个例子来说明如何通过eclispe自动生成.h头文件,适合初学者。本篇文章主要是参考:http://blog.csdn.net/super_level/article/details/21243533。

1 创建含有本地代码的Android Project

该过程分为以下两步:

  • 创建普通的Android Application工程(注意最小支持的API版本要不小于14)
  • 加入本地代码支持  目的是可以自动生成.so文件,以便在MainActivitiy中能够加载库文件从而调用c/c++
创建工程:

加入本地代码支持:

名字选择默认的TestNDK就可以了。

完成结果:

2 编写java端代码和c++端代码

2.1 java端代码

Java端,注意不要继承自Android中的类,否则javah编译头文件时要指定android类路径。

在NativeClass.java文件中:

package com.example.testndk;

import android.util.Log;

public class NativeClass {
	//数组a中的每个元素都加上b,返回值为在C++中数据是否为a中数据拷贝得到的(按值拷贝还是传递指针)  
    public static native boolean jniArrayAdd(int[] a, int b);  //加
  // 在C++中创建Java中的int数组,其中元素为 数组a中的对应元素乘以b  
    public static native int[] jnitArrayMul(int[] a,int b);  //乘以
    static {  
        Log.i("NativeClass","before load library");  
        System.loadLibrary("TestNDK");//注意这里为自己指定的.so文件,无lib前缀,亦无后缀  
        Log.i("NativeClass","after load library");    
    }  
}

Java端调用JNI方法的代码:
将MainActivity改为:

package com.example.testndk;

import java.util.Arrays;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		TextView tv = new TextView(this);
		int[] array = new int[]{1,2,3};
		String str = "数组,调用C++前" + Arrays.toString(array);//将数组转成字符串
		boolean isCopyOfArrayInCpp = NativeClass.jniArrayAdd(array, 1);
		System.out.println(isCopyOfArrayInCpp);//然后java在print的时候都是调用对象的toString方法就会把o改成false输出
		str += "\n 在c++中为副本?  " + isCopyOfArrayInCpp;
		str += "\n数组,调用C++后:" + Arrays.toString(array);
		tv.setText(str);
		setContentView(tv);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

2.2 编写c++代码,实现java中native函数

#include <jni.h>
#include "com_example_testndk_NativeClass.h"
#include <android/log.h>
#ifdef __cplusplus
extern "C"{
#endif
JNIEXPORT jboolean JNICALL Java_com_example_testndk_NativeClass_jniArrayAdd
  (JNIEnv * env, jclass, jintArray array, jint b){
	jsize size = env ->GetArrayLength(array);

	jboolean isCopy = false;
	jint *pArray = (jint*) env ->GetPrimitiveArrayCritical(array,&isCopy);
	for(int i = 0; i < size ; i++){
		pArray[i] += b;
	}
	env->ReleasePrimitiveArrayCritical(array,pArray,JNI_COMMIT);//JNI_COMMIT 对java数组进行更行,但是不释放java数组
	__android_log_print(ANDROID_LOG_DEBUG, "frank", "isCopy= %d",isCopy);//输出的的isCopy= 0;说明是false,0是false也是Null(string 输出的时候)
	return isCopy;
}
#ifdef __cplusplus
}
#endif
如果要log输出的话,android.mk里面需要配置:


添加:LOCAL_LDLIBS := -landroid -llog {这个库文件}

3 配置自动生成头文件:

3.1 对每一个程序配置javah命令

配置如下:

里面需要写的分别是:

C:\Program Files\Java\jdk1.7.0_51\bin\javah.exe 

${workspace_loc:/WifiIp}

-classpath src -d jni com.example.wifiip.MainActivity(注意这种写法是在MainAvitvity里面去声明native方法的时候写的一种格式)

然后再run里面执行 wifiip_javah 就可以了(这里并不是TestNDK这个工程,换了另外一个工程)

3.2 通用的头文件生成配置如下

如果每一个程序都像上面一样去配置是不是会很麻烦,所以就有一种通用的配置:

需要填的分别是:

Generate C and C++ Header

C:\Program Files\Java\jdk1.7.0_51\bin\javah.exe

${project_loc}/jni

-classpath "${project_classpath};${env_var:ANDROID_SDK_HOME}/platforms/android-14/android.jar"${java_type_name}

注意这个ANDROID_SDK_HOME,需要在path环境变量里面去配置:


在尾部加上D:\program\studyprogram\adt-bundle-windows-x86-20130219\sdk;(你的SDK的路径)

然后配置好之后。就可以用这个命令去生成.h头文件了,注意生成的时候一定要:






4 配置生成的.so文件的目标平台

ava是跨平台的可是C++生成动态链接文件不是!!!同是Android,底层的CPU架构不同,动态链接文件也不同。。。好吧,这个我不知道原因。。。
于是乎,还得为不同的CPU创建不同的动态链接库文件,好在一行命令搞定~所有的动态链接一起打包,管他是哪个CPU,统统适用,Happy啊。


再编译时在libs下面就会生成三种平台下的.so文件。

5 结果


后续:要进行对jni层进行调试。比较麻烦。等用到的时候再去学习吧。

这样就把整个java层调用c/c++层说明了。

工程下载链接地址http://download.csdn.net/detail/u011563903/8301923

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Frank范

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值