Android + NDK + Eclipse 调试

这两天在倒腾NDK, 算是小告一段落,下面就说说Eclipse下面 NDK plugin的配置以及如何在 Eclipse下面调试 native 代码。


PS: 也是参照网上的文章做的,本来打算直接摘抄他的,结果当时没有保存,算了,直接自己写一篇了。


准备工作

  1. 安装Android SDK 和 NDK, 这个不多说啦,网上很多
  2. 安装Eclipse插件
    • Help -> Install New Software -> Add, 添加软件源, location 为 https://dl-ssl.google.com/android/eclipse/, Name自己决定。
    • 选中刚才添加的源,把出来的两个都安装上。上面那个是ADT插件,下面那个是NDK对应的插件。
  3. 同样的,安装CDT, 软件源为 http://download.eclipse.org/tools/cdt/releases/indigo. 我用的Eclipse是 indigo版本,如果你的不是的话,那么找到对应的源并安装就好了。
不懂的话可以参考 Using the NDK plugin来。 



工具配置

接下来配置 ADT路径和 NDK 路径, 如果ADT的已经配置好了就不用管啦。Elipse菜单, Window -> Preference, 左边,点开 Android标签页,把Android SDK路径填上,对应的还有 NDK 的路径:

至此,全局的工作已经搞定了。


NDK项目

创建项目

新建一个Android Application项目, Application Name 配置如下,后面全部默认。


添加 NDK 支持

选中项目,右键, Android Tools->Add Native Supports, 会冒出来一个对话框,教你输入一个lib名字,实际上就是最后生成的动态链接库的名字,默认就是之前设置的项目名称,当然你也可以自己修改。

native 代码调用

  1. 上一步完成之后,会在项目根目录下面创建一个 jni目录,下面有一个 NdkTest.cpp文件和一个Android.mk 文件;
  2. 接下来,就是在java代码里面添加 native 函数声明, 并调用这个函数来测试,将MainActivity.java 里面修改如下:
public class MainActivity extends Activity {
	native String ndkTest();
	
	static {
		System.loadLibrary("NdkTest");
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		TextView tView = new TextView(this);
		tView.setText( ndkTest() );
		setContentView(tView);          
	}
        // others don't have to change 

生成 Native 函数接口

调用javah生成头文件,然后手动将这个头文件放到jni目录下面, 实际上,这一步并不是必须的,如果你知道jni中函数的命名规范,自己在NdkTest.cpp 里面添加对应的函数实现就好了,不过,为了避免出错,还是使用 javah 来自动生成C\C++函数接口比较好, 操作步骤的话,很简单
    • 切换到 jni目录下面
    • 输入
      javah -jni -classpath ../bin/classes -o ./ndkTest.h com.example.NdkTest.MainActivity 
      
    具体的命令参数可以看javah的帮助文档,注意,类名,也就是 com.example.NdkTest.MainActivity 一定要放在最后。 你也可以参考我的另 一篇笔记来构建一个Builder自动生成头文件 NdkTest.h。不管怎么样,最后 NdkTest.h 内容如下:
  1. /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_example_ndktest_MainActivity */
    
    
    #ifndef _Included_com_example_ndktest_MainActivity
    #define _Included_com_example_ndktest_MainActivity
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_example_ndktest_MainActivity
     * Method:    ndkTest
     * Signature: ()Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL Java_com_example_ndktest_MainActivity_ndkTest
      (JNIEnv *, jobject);
    
    
    #ifdef __cplusplus
    }
    #endif
    #endif

实现Native函数

在NdkTest.cpp文件里面包含 ndkTest.h, 并实现对应的函数:
#include <jni.h>
#include "ndkTest.h"

JNIEXPORT jstring JNICALL Java_com_example_ndktest_MainActivity_ndkTest
  (JNIEnv *env, jobject obj)
{
	return (*env).NewStringUTF("Just a test");
}
注意,虽然 ndkTest.h 里面有 <jni.h> 头文件包含,但是如果 ndkTest.cpp 里面没有的话,Eclipse会无法自动完成函数提示。也可能是我没有配置好。

编译

接下来,Project-> Build Project, 就能够编译得到动态链接库文件了。
TIPS: 不过,如果你的Eclipse设置没怎么修改的话(就像我的一样),可能会有如下错误
APP_PLATFORM android-14 is larger than android:minSdkVersion 8 in ./AndroidMainfest.xml
可以按照 这里来修改, Window -> Preferences -> C\C++ -> Build -> Settings, 选择右边的 CDT GNU C/C++ Error Parser, 添加一条规则并将它置顶,如下:
上面的设置需要注意前两个冒号后面的空格不能少, 我把空格用下划线替代,应该是这个样子:
(.*?):_Android NDK:_WARNING:(.*)
如果一切顺利的话,就会生成 libNdkTest.so, 并复制到 libs/armeabi 目录下面。 Ctrl + F11 就可以运行程序了。

如果运行失败,确保在MainActivity.java 里面有添加\
static {
    System.loadLibrary("NdkTest");
}
这一句话的作用就是加载所调用的动态链接库文件,这里就是 libNdkTest.so。



调试Native code

接下来就是重头戏啦,使用eclipse来调试代码。 

生成可调试代码

首先在编译的时候保证代码可调试,Project -> Properties, 选择 C/C++ Build,  去掉 Use default build command 前面的勾, 在编译命令后面加上 NDK_DEBUG=1, 注意等号前后没有空格:

OK 之后, Project -> Build Project, 然后看Console输出窗口,如果看到Gdb字样,说明调试版本编译成功:


调试

不过,离见证奇迹的时刻还差一点, 这里 有说( Known Issues上面的那个 NOTE),native 调试的启动器相对与Android应用的启动有一个延时,也就是很有可能你的 native code都调用完毕了,调试器还木有启动,断点神马的对它来说可能就是个毛线啦。 不过,也有办法来解决。在调试的时候,把 native 函数调用放到一个OnClickLinstener函数里面去,比如,可以这样修改 MainActivity 里面的 OnCreate函数:
@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		TextView tView = new TextView(this);
		tView.setText( "Do you dare to click me???");
		
		tView.setOnClickListener( new OnClickListener() {			
			@Override
			public void onClick(View v) {
				((TextView)v).setText( ndkTest() );
			}
		});
		
		setContentView(tView);
	}

然后,在 NdkTest.cpp 的 ndkTest 函数里面设置断点,这个,不用我多说了吧!
接下来,Run -> DebugAs -> Android Native Application
等到程序启动完毕之后,并且Eclipse console窗口有类似如下输出,说明调试器加载完毕(或者是eclipse出现是否进入调试页面,我的设置为默认了,所以不太确定是不是会提示):


最后,见证奇迹的时刻,激动人心的时刻,come come come coming....  点击一下程序主界面:

 嘿嘿嘿,一切尽在不言中。。。。

(这里,为了设断点,我加了两条语句,如果你也修改了 NdkTest.cpp 的话,需要重新 Build Project)


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值