java中通过ndk调用c/c++ 例子,详细解释
2014-12-25 12:54
531 查看
上篇文章中已经介绍了,关于NDK开发环境的搭建,这里不做赘述。这篇文章主要是通过一个例子来说明如何通过eclispe自动生成.h头文件,适合初学者。本篇文章主要是参考:http://blog.csdn.net/super_level/article/details/21243533。
创建普通的Android Application工程(注意最小支持的API版本要不小于14)
加入本地代码支持 目的是可以自动生成.so文件,以便在MainActivitiy中能够加载库文件从而调用c/c++
创建工程:
加入本地代码支持:
名字选择默认的TestNDK就可以了。
完成结果:
在NativeClass.java文件中:
Java端调用JNI方法的代码:
将MainActivity改为:
添加:LOCAL_LDLIBS := -landroid -llog {这个库文件}
配置如下:
里面需要写的分别是:
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这个工程,换了另外一个工程)
需要填的分别是:
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头文件了,注意生成的时候一定要:
于是乎,还得为不同的CPU创建不同的动态链接库文件,好在一行命令搞定~所有的动态链接一起打包,管他是哪个CPU,统统适用,Happy啊。
再编译时在libs下面就会生成三种平台下的.so文件。
后续:要进行对jni层进行调试。比较麻烦。等用到的时候再去学习吧。
这样就把整个java层调用c/c++层说明了。
工程下载链接地址http://download.csdn.net/detail/u011563903/8301923
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
相关文章推荐
- scala和java通过JNI调用C++程序例子
- Android-NDK开发之第四个例子--用C/C++调用Java
- NDK开发(1)——JAVA通过JNI调用C代码详细步骤
- Android-NDK开发之第四个例子--用C/C++调用Java
- Android-NDK开发之第四个例子--用C/C++调用Java
- 在eclipse下,JAVA通过JNI调用C++方法的简单例子(非android)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)