- 浏览: 692489 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (181)
- Matlab (16)
- Java (26)
- autoHotkey (4)
- openCV (1)
- C++ (50)
- PDF-XChange Viewer (2)
- 学术 (11)
- javascript (4)
- linux (11)
- SWT (9)
- latex (7)
- GAE (2)
- windows (6)
- C# (3)
- PS (20)
- JNI (4)
- latex,批处理 (0)
- 批处理 (4)
- Android (5)
- 矩阵论 (1)
- SVM (1)
- 概率图模型 (0)
- Python (12)
- Eigen (5)
- 编程题 (1)
- MKL (1)
- 神经网络 (9)
- 最优化 (2)
- 摄影 (1)
- PPT (0)
- After Effects (3)
- CUDA (3)
- caffe (0)
- MXNet (2)
- svn (1)
- R (0)
- 虚拟机 (0)
- tensorflow (7)
- theano (1)
- Keras (1)
- vim (1)
- xgboost (1)
- spark (6)
- eclipse (2)
- word2vec (0)
- hadoop (1)
- dmlc (1)
- git (0)
最新评论
-
jeffersonz:
请问大神,这个插件记录下来的脚本为什么不能再Extendscr ...
PhotoShop - 记录PS的所有操作为JavaScript代码 -
cherishLC:
Andy__Zou 写道cherishLC 写道Andy__Z ...
Eigen的编译选项;MKL的使用 -
Andy__Zou:
cherishLC 写道Andy__Zou 写道cherish ...
Eigen的编译选项;MKL的使用 -
cherishLC:
Andy__Zou 写道cherishLC 写道Andy__Z ...
Eigen的编译选项;MKL的使用 -
Andy__Zou:
cherishLC 写道Andy__Zou 写道 您好,您的工 ...
Eigen的编译选项;MKL的使用
在Android中调用C++其实就是在Java中调用C++代码,只是在windows下编译生成DLL,在Android中会生成Linux系统下的.so文件(好吧,其实我基本没用过Linux)。
没写过JNI的可以看看我之前的博客(Windows下利用Visual Studio开发的过程):http://cherishlc.iteye.com/admin/blogs/1328136
以及自动生成工具swig的使用方法(数组的支持不好!其他挺方便):http://cherishlc.iteye.com/admin/blogs/1689224
另外推荐一篇非常不错的NDK博文,(配置忽略,主要是各种数据的传递,下代码看看吧)http://vaero.blog.51cto.com/4350852/782787
扯远了,下面来看看真正在Android中的开发过程。
1、下载ADT及NDK
其中ADT中包含了Eclipse及google的开发套件,不用写C++的下载ADT就足够了。
NDK则是包含了GCC的编译器,以及各个平台(arm,X86,MIPS)的相关头文件,交叉编译的一些平台相关文件等。
2、在ADT中配置NDK路径
解压NDK压缩包到任意路径,按下图在ADT中(也即ADT解压后的Eclipse文件下的Eclipse中)设置NDK的路径。
设置方法如下图所示:
3、创建含有本地代码的Android Project
该过程分为以下两步:
具体过程如下图所示:
创建工程:
加入本地代码支持:
完成情况:
点击菜单栏Project->Build All命令进行编译。
注意:如果之前最小支持的API版本要不小于14,将出现编译错误。“Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 7 in ./AndroidManifest.xml”
解决方法如下:
打开AndroidManifest.xml,切换到源文件视图,将minSdkVersion 改为14以上:
4、编写Java端代码和C++端代码
Java端,注意不要继承自Android中的类,否则javah编译头文件时要指定android类路径。
javah推荐两种方法:
在Eclipse中配置javah外部工具方法为:
上图中最长的一行命令如下:
配置好之后:
点刚才配置好的javah工具,生成.h文件,然后:
Java端调用JNI方法的代码:
将MainActivity改为:
编写C++代码:
打开刚才系统生成的TestNDK2.cpp,修改成如下样子:
5、配置生成的.so文件的目标平台
Java是跨平台的可是C++生成动态链接文件不是!!!同是Android,底层的CPU架构不同,动态链接文件也不同。。。好吧,这个我不知道原因。。。
于是乎,还得为不同的CPU创建不同的动态链接库文件,好在一行命令搞定~所有的动态链接一起打包,管他是哪个CPU,统统适用,Happy啊。
参考自:http://bbs.csdn.net/topics/390158301
过程如下:
再编译时会发现生成了对应以上四个平台的.so文件~~~
一切搞定,可以运行了!!!运行结果如下:
6、Java与C++联合调试
参见:http://blog.csdn.net/wjr2012/article/details/7993722
注意:
过程为:
右键点击工程文件, 在properties -> C/C++ Build中:
完了设置断点(只能在C++中)就可以启动调试了~~
好吧,,,调试怎么不灵光呢。。。再想想刚才的注意事项。。。好吧,早执行完了JNI代码了。。。
于是乎,修改MainActivity代码如下:
运行到断点的结果:
不好意思啊,,我一年多没碰Android了。。。
好久没整了,不好意思,不知道是不是要手动添加编译选项 NDK_DEBUG=1:http://blog.csdn.net/stalendp/article/details/8807603
呃, 写完这文章就没再整这东西了,ADT或NDK是直接包含C++编译工具的吧;
要是只在windows下开发 看看是不是eclipse中windows->preference下的C++工具中没设置路径?
谢谢支持~
没写过JNI的可以看看我之前的博客(Windows下利用Visual Studio开发的过程):http://cherishlc.iteye.com/admin/blogs/1328136
以及自动生成工具swig的使用方法(数组的支持不好!其他挺方便):http://cherishlc.iteye.com/admin/blogs/1689224
另外推荐一篇非常不错的NDK博文,(配置忽略,主要是各种数据的传递,下代码看看吧)http://vaero.blog.51cto.com/4350852/782787
扯远了,下面来看看真正在Android中的开发过程。
1、下载ADT及NDK
- 下载ADT (Android Developer Tools) Bundle:http://developer.android.com/sdk/index.html
- 下载NDKhttp://developer.android.com/tools/sdk/ndk/index.html
其中ADT中包含了Eclipse及google的开发套件,不用写C++的下载ADT就足够了。
NDK则是包含了GCC的编译器,以及各个平台(arm,X86,MIPS)的相关头文件,交叉编译的一些平台相关文件等。
2、在ADT中配置NDK路径
解压NDK压缩包到任意路径,按下图在ADT中(也即ADT解压后的Eclipse文件下的Eclipse中)设置NDK的路径。
设置方法如下图所示:
3、创建含有本地代码的Android Project
该过程分为以下两步:
- 创建普通的Android Application工程(注意最小支持的API版本要不小于14)
- 加入本地代码支持
具体过程如下图所示:
创建工程:
加入本地代码支持:
完成情况:
点击菜单栏Project->Build All命令进行编译。
注意:如果之前最小支持的API版本要不小于14,将出现编译错误。“Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 7 in ./AndroidManifest.xml”
解决方法如下:
打开AndroidManifest.xml,切换到源文件视图,将minSdkVersion 改为14以上:
4、编写Java端代码和C++端代码
Java端,注意不要继承自Android中的类,否则javah编译头文件时要指定android类路径。
package com.lc.testndk2; 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("TestNDK2");//注意这里为自己指定的.so文件,无lib前缀,亦无后缀 Log.i("NativeClass","after load library"); } }
javah推荐两种方法:
- 使用我写的工具,含本地方法的类多时,一次编译完成:http://cherishlc.iteye.com/blog/1326893
- 在Eclipse中配置外部工具,配置方法参考自(同时也是讲Android中JNI配置方法的博客):http://www.cnblogs.com/yemeishu/archive/2012/12/24/NDK%E5%BC%80%E5%8F%91.html
在Eclipse中配置javah外部工具方法为:
上图中最长的一行命令如下:
-v -classpath "${project_loc}/bin/classes" -d "${project_loc}/jni" ${java_type_name}
配置好之后:
点刚才配置好的javah工具,生成.h文件,然后:
Java端调用JNI方法的代码:
将MainActivity改为:
package com.lc.testndk2; import java.util.Arrays; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); int[] array = new int[] { 1, 2, 3}; String str = "数组,调用C++前" + Arrays.toString(array); boolean isCopyOfArrayInCpp = NativeClass.jniArrayAdd(array, 1); str += "\n在C++中为副本? " + isCopyOfArrayInCpp; str += "\n数组,调用C++后:" + Arrays.toString(array); tv.setText(str); setContentView(tv); } }
编写C++代码:
打开刚才系统生成的TestNDK2.cpp,修改成如下样子:
#include <jni.h> #include "com_lc_testndk2_NativeClass.h" #ifdef __cplusplus //最好有这个,否则被编译器改了函数名字找不到不要怪我 extern "C" { #endif /* * Class: com_lc_testndk2_NativeClass * Method: jinArrayAdd * Signature: ([II)[I */JNIEXPORT jboolean JNICALL Java_com_lc_testndk2_NativeClass_jniArrayAdd( JNIEnv * env, jclass, jintArray array, jint b) { jsize size = env->GetArrayLength(array); // jintArray sum=env->NewIntArray(2); jboolean isCopy; jint* pArray = (jint*) env->GetPrimitiveArrayCritical(array, &isCopy); for (int i = 0; i < size; i++) pArray[i] += b; env->ReleasePrimitiveArrayCritical(array, pArray, JNI_COMMIT); //env->ReleasePrimitiveArrayCritical(sum,pSum,JNI_COMMIT); return isCopy; } /* * Class: com_lc_testndk2_NativeClass * Method: jnitArrayMul * Signature: ([II)[I */JNIEXPORT jintArray JNICALL Java_com_lc_testndk2_NativeClass_jnitArrayMul( JNIEnv * env, jclass, jintArray array, jint b) { jsize size = env->GetArrayLength(array); jintArray product = env->NewIntArray(size); jint* pArray = (jint*) env->GetPrimitiveArrayCritical(array, 0); jint* pProduct=(jint*)env->GetPrimitiveArrayCritical(product,0); // jintArray product = env->NewIntArray(size); //不能在这里创建!!因为上面的方法会使java进入critical region, 在这里创建的话虚拟机直接崩溃 for (int i = 0; i < size; i++) pProduct[i] =pArray[i]* b; env->ReleasePrimitiveArrayCritical(array, pArray, JNI_COMMIT); env->ReleasePrimitiveArrayCritical(product,pProduct,JNI_COMMIT); return product; } #ifdef __cplusplus } #endif
5、配置生成的.so文件的目标平台
Java是跨平台的可是C++生成动态链接文件不是!!!同是Android,底层的CPU架构不同,动态链接文件也不同。。。好吧,这个我不知道原因。。。
于是乎,还得为不同的CPU创建不同的动态链接库文件,好在一行命令搞定~所有的动态链接一起打包,管他是哪个CPU,统统适用,Happy啊。
参考自:http://bbs.csdn.net/topics/390158301
过程如下:
再编译时会发现生成了对应以上四个平台的.so文件~~~
一切搞定,可以运行了!!!运行结果如下:
6、Java与C++联合调试
参见:http://blog.csdn.net/wjr2012/article/details/7993722
注意:
- C++的调试器有几秒的延迟才能启动好,也就是程序运行了一会儿才可以开始调试,所以要调试的代码一定要是几秒钟后才能调试!!!
- 断点设置在C++中才有效。。。
过程为:
右键点击工程文件, 在properties -> C/C++ Build中:
完了设置断点(只能在C++中)就可以启动调试了~~
好吧,,,调试怎么不灵光呢。。。再想想刚才的注意事项。。。好吧,早执行完了JNI代码了。。。
于是乎,修改MainActivity代码如下:
package com.lc.testndk2; import java.util.Arrays; import java.util.Timer; import java.util.TimerTask; import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.widget.TextView; /** * @author LC * *完整的演示Android通过JNI调用C++代码的工程 */ public class MainActivity extends Activity { TextView tv = null; int count = 0; Timer timer; @SuppressLint("HandlerLeak") class MyHandler extends Handler{ @Override public void handleMessage(Message msg) { if (tv != null) { tv.setText(msg.getData().getString("text")); } super.handleMessage(msg); } }; Handler handle= new MyHandler(); class refreshTask extends TimerTask { @Override public void run() { try { count++; Log.i("MainActivity", "before call native code,count=" + count); int[] array = new int[] { count, -count, 2*count }; String str = "第" + count + "次了\n"; str += "数组,调用C++前" + Arrays.toString(array); boolean isCopyOfArrayInCpp = NativeClass.jniArrayAdd(array,1); str += "\n在C++中为副本? " + isCopyOfArrayInCpp; str += "\n数组,调用C++后:" + Arrays.toString(array)+"\n\n"; str+="测试在C++中创建数组:\n"; str += Arrays.toString(array)+"* 2 ="; str+=Arrays.toString(NativeClass.jnitArrayMul(array, 2))+"\n\n"; Message msg=new Message(); Bundle b=new Bundle(); b.putString("text", str); msg.setData(b); handle.sendMessage(msg); Log.i("MainActivity", "after call native code"); } catch (Exception e) { Log.i(MainActivity.class.getSimpleName(), e.toString()); e.printStackTrace(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); tv = new TextView(this); tv.setText("我是初始值"); setContentView(tv); } @Override protected void onPause() { Log.i(MainActivity.class.getSimpleName(),"onPuase()"); timer.cancel(); timer=null; super.onPause(); } @Override protected void onResume() { Log.i(MainActivity.class.getSimpleName(),"onResume()"); timer=new Timer(); timer.scheduleAtFixedRate(new refreshTask(), 0, 1000); super.onResume(); } }
运行到断点的结果:
- TestNDK2.rar (710.1 KB)
- 下载次数: 322
评论
13 楼
cherishLC
2014-04-14
hrybird 写道
您好,我用ndk将之前windows下的2款软件都能成功编译和基本测试通过了,但始终没法进行调试,每次Debug As->Android Native Application操作后,就显示先编译成功,然后后面没反应了,不会显示虚拟器的界面。
是否可以帮忙看看,非常感谢。 QQ:285026198
是否可以帮忙看看,非常感谢。 QQ:285026198
不好意思啊,,我一年多没碰Android了。。。
12 楼
hrybird
2014-04-10
您好,我用ndk将之前windows下的2款软件都能成功编译和基本测试通过了,但始终没法进行调试,每次Debug As->Android Native Application操作后,就显示先编译成功,然后后面没反应了,不会显示虚拟器的界面。
是否可以帮忙看看,非常感谢。 QQ:285026198
是否可以帮忙看看,非常感谢。 QQ:285026198
11 楼
天下无敌工作室
2013-12-03
APP_ABI := all 即可!
10 楼
liuhe556
2013-10-24
楼主辛苦了!非常感谢,你做了件非常有意义的事情!拜读了,受用了,收cang了!!!
9 楼
xianni1079054314
2013-09-24
终于把项目做成了!灰常感谢!
8 楼
cherishLC
2013-08-26
guoxinya86 写道
楼主你好,我下了附件,调试提示这个:
[2013-08-26 14:06:56 - TestNDK2] gdbserver output:
[2013-08-26 14:06:56 - TestNDK2] run-as: Package 'com.lc.testndk2' has corrupt installation
[2013-08-26 14:06:56 - TestNDK2] Verify if the application was built with NDK_DEBUG=1
[2013-08-26 14:06:56 - TestNDK2] gdbserver output:
[2013-08-26 14:06:56 - TestNDK2] run-as: Package 'com.lc.testndk2' has corrupt installation
[2013-08-26 14:06:56 - TestNDK2] Verify if the application was built with NDK_DEBUG=1
好久没整了,不好意思,不知道是不是要手动添加编译选项 NDK_DEBUG=1:http://blog.csdn.net/stalendp/article/details/8807603
7 楼
guoxinya86
2013-08-26
楼主你好,我下了附件,调试提示这个:
[2013-08-26 14:06:56 - TestNDK2] gdbserver output:
[2013-08-26 14:06:56 - TestNDK2] run-as: Package 'com.lc.testndk2' has corrupt installation
[2013-08-26 14:06:56 - TestNDK2] Verify if the application was built with NDK_DEBUG=1
[2013-08-26 14:06:56 - TestNDK2] gdbserver output:
[2013-08-26 14:06:56 - TestNDK2] run-as: Package 'com.lc.testndk2' has corrupt installation
[2013-08-26 14:06:56 - TestNDK2] Verify if the application was built with NDK_DEBUG=1
6 楼
wqchen
2013-08-23
nice,喜欢这类让初学者明白的文章
5 楼
cherishLC
2013-07-23
萧_瑟 写道
您好,请问怎么利用这个工具编译C项目呢,我的一直编译不成功。错误:Error: Program "make" is not found in PATH 按照网上说的,也装了MinGW,也设置了系统变量,可是Ctrl+B 编译还是这个错误。你知道怎么建一个简单的C项目吗?
呃, 写完这文章就没再整这东西了,ADT或NDK是直接包含C++编译工具的吧;
要是只在windows下开发 看看是不是eclipse中windows->preference下的C++工具中没设置路径?
4 楼
萧_瑟
2013-07-16
您好,请问怎么利用这个工具编译C项目呢,我的一直编译不成功。错误:Error: Program "make" is not found in PATH 按照网上说的,也装了MinGW,也设置了系统变量,可是Ctrl+B 编译还是这个错误。你知道怎么建一个简单的C项目吗?
3 楼
lucherr
2013-07-16
不错,谢谢分享,写的很棒!
2 楼
cherishLC
2013-01-07
yingxiaosan 写道
很详细,辛苦啊辛苦,受教了!!!
谢谢支持~
1 楼
yingxiaosan
2013-01-05
很详细,辛苦啊辛苦,受教了!!!
发表评论
-
Android中启动外部程序
2015-01-12 20:48 11621、启动外部程序 引用自:http://blog.csdn.n ... -
Android学习笔记——NDK中C++标准库、STL的配置;Include其他头文件
2013-01-09 21:55 18750以下所有是基于Eclipse的,使用命令行的绕道。 1、ST ... -
Android 学习笔记——采用Intel HAXM对模拟器进行加速
2012-12-26 12:58 5888开个模拟器那叫一个慢啊,网上有用VMWare虚拟机加速的,懒得 ... -
Android 学习笔记——旋转模拟器方向,全屏,窗口生命周期
2012-12-25 22:14 25421、下载及安装SDK,入门示例 直接到以下页面下载一个ADT ... -
JNI中基本类型数组的传递方法(无需拷贝数据!!!)
2012-10-23 17:11 183760、先来看一下主要用到哪些函数: GetIntArrayEle ... -
swig--在java、C#中调用c++写的DLL(以vs2012配置为例)
2012-10-02 22:06 72401、下载、安装: 到http://www.swig.org/d ... -
JNI学习笔记,含VS配置x64平台的问题
2011-12-27 22:13 78591、来个java程序,本地 ...
相关推荐
### Android学习笔记含JNI、USB和ftdi通信方式详解 #### 项目四:多线程文件下载 在Android开发中,文件下载是一个常见的需求。利用多线程技术可以提高文件下载的速度,尤其在网络条件较差的情况下更为明显。多...
9. **JNI(Java Native Interface)**:当JAVA代码需要调用本地(C/C++)代码时,JNI提供了桥梁,学习笔记会介绍如何使用JNI进行跨语言交互。 10. **JAVA标准库**:包括JDBC(数据库连接)、Swing(GUI开发)、JAXP...
1. **性能优化**:某些计算密集型的任务,如果用C/C++编写并利用JNI调用,相比纯Java代码会有更高的执行效率。 2. **复用现有C/C++代码**:如果已有大量的C/C++代码需要在Android应用中使用,可以通过JNI直接调用...
### Java与C++交互(JNI学习笔记) #### 一、Java类型与C/C++类型对应关系 在Java Native Interface (JNI) 中,Java 和 C/C++ 的数据类型有着明确的对应关系。理解这些对应关系是实现Java与C++交互的基础。 - **...
15. **JNI(Java Native Interface)**:Java的本地接口允许Java代码调用C/C++的库,实现性能优化或调用特定平台的功能。 Java JDK 6学习笔记——PPT简体版将详细解析以上知识点,通过实例演示和清晰的讲解,帮助...
本笔记主要探讨了Android NDK的使用、安装、配置以及在Android应用开发中的实践。 一、Android NDK简介 NDK为开发者提供了在Android平台上进行原生代码编程的能力,这包括对底层硬件的直接访问和优化,比如图形处理...
### JNI学习笔记详解 #### 一、JNI简介 JNI(Java Native Interface)是Java平台提供的一种强大机制,它允许Java程序直接调用本地代码(通常是C或C++编写)。这为Java应用程序带来了额外的灵活性,使得开发者能够...
这个压缩包的“NDK学习笔记”可能涵盖了这些内容,包括如何设置开发环境、创建和调用本地方法、处理不同类型的数据(如数组、对象等)、以及在Android中使用NDK的特定细节,如Android.mk或CMakeLists.txt构建文件的...
JNI在Android开发中扮演着重要角色,因为有时我们需要利用C或C++的高性能来实现某些功能,比如图像处理、游戏引擎或底层硬件交互。 在Android Studio中,通常我们使用Gradle作为构建工具。而“gradle-experimental...
JNI在Android开发中尤其重要,因为它是Java与本地C/C++代码沟通的桥梁,尤其是在处理高性能计算、底层库调用或者利用硬件特性时。NDK(Native Development Kit)则是Android开发中的一个工具集,它提供了编译C/C++...
4. **性能优化**:通过JNI调用本地代码可以提升计算密集型任务的执行效率,学习如何利用这一特性来优化应用。 5. **跨平台兼容性**:了解如何确保JNI代码在不同平台上的一致性和兼容性。 总之,这份资料对于想要...
本节详细介绍了一个简单的“Hello World”示例,演示了如何使用NDK在Android应用中加入本地代码。 1. **创建Android工程**:使用Eclipse或其他IDE创建一个新的Android工程。 2. **添加NDK支持**:右键点击项目,...
JNI,全称Java Native Interface,是Java平台标准的一部分,它为Java程序员提供了一种方法,可以在Java代码中调用本地(非Java)代码,反之亦然。JNI在Android开发中尤其重要,因为许多系统级功能和性能优化都依赖于...
"biji.txt"可能是笔记、日志或其他辅助资料,它可能包含了一些开发者在学习和使用JNI过程中记录的信息。 总的来说,这个压缩包提供了一个全面的学习资源,涵盖了JNI的基础知识、调用流程、编程规范和实例,适合...
本学习笔记将深入探讨三种主要的Java调用DLL的方法:JNI(Java Native Interface)、JACOB(Java COM Bridge)以及JAWIN,并介绍一些实用的DLL查看工具。 1. **JNI(Java Native Interface)**: JNI是Java平台的...
标题中提到了“嵌入式开发学习笔记”,这意味着笔记内容涉及了嵌入式系统的开发过程,主要使用了Java和C/C++语言。这种学习笔记对于初学者来说是非常有价值的,因为它能够帮助他们理解如何从零基础开始学习嵌入式...