首页 > 代码库 > windows下android NDK 环境配置

windows下android NDK 环境配置

0、下载jdk并配置环境变量

下载最新jdk,百度搜索“jdk”就有了。安装完成后,配置环境变量(网上一搜,一堆,我这里仅作简要叙述)

  1.     计算机→属性→高级系统设置→高级→环境变量。
  2. 系统变量→新建 JAVA_HOME 变量 。变量值填写jdk的安装目录(本人是 D:\Program Files\Java\jdk1.7.0_45)
  3. 系统变量→新建 CLASSPATH 变量

    变量值填写   .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar(注意最前面有一点)

  4. 系统变量→寻找 Path 变量→编辑

    在变量值最后输入 %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;

    (注意原来Path的变量值末尾有没有;号,如果没有,先输入;号再输入上面的代码)

    系统变量配置完毕

 

 

1、官网下载最新的ADT。 解压即可(eclipse最好自带ndk插件)

2、官网下载最新的NDK。解压即可(ndkr7以上有自带cygwin)

3、eclipse没有自带插件,则下载插件。

插件网上有,我作为自己学习,也在百度云共享了一份,下载地址:http://pan.baidu.com/s/1i3xImQp

下载好插件放到eclipse下的plugins文件夹下。重启eclipse。

 

 

4、重点开始

eclipse→window→preferences→Android→NDK

配置刚刚下载的ndk的路径

5、新建android 项目

  右击→properties→C/C++ Build 。去掉默认的build command  

  设置成${NDKROOT}/ndk-build.cmd 

 

再到build Variables 点击add。配置如图.name:NDKROOT  value:你的ndk路径。点击确定。

 

 

6、项目右键->Android Tools->Add Native Support...,输入.so库名字后点击Finish

7、现在已经可以Build我们的Jni项目了,选择项目,Project->Build Project,编译我们的c/c++代码,此时项目结构如下,NDK plugin已经为我们添加好了include,已经为我们生成了相应的Android.mk以及 cpp文件。(注意:这里插件为我们生成的是cpp文件,若你不喜欢可以改回.c,并在mk文件中进行相应更改)

8、可以运行我们的Jni项目了。

 

遇到的问题

1、运行c++生成的.so库,若报以下错误:(既找不到函数)

No implementation found for native Lcom/example/hellojni/MainActivity;.stringFromJNI ()Ljava/lang/String;

java.lang.UnsatisfiedLinkError: stringFromJNI

at com.example.hellojni.MainActivity.stringFromJNI(Native Method)

解决方法:

为供Java调用的c++函数前加入extern "C" 修饰,如:(NDK example里面的cpp文件也是这么声明的,参考hello-gl2)

 

[java] view plaincopy
 
 
  1. extern "C" {  
  2.     JNIEXPORT jstring JNICALL Java_com_dgut_android_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz );  
  3. }  
  4.   
  5. JNIEXPORT jstring JNICALL Java_com_dgut_android_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz )  
  6. {  
  7.     return env->NewStringUTF("Hello from JNI bear c++");  
  8. }  

原因是:

 

        被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。

        首先看看C++中对类似C的函数是怎样编译的:作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:void foo( int x, int y );该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数voidfoo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。
        同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

        因此,若我们没有使用extern "C"修饰函数,按照C语言方式编译和连接,Jni调用将可能找不到该函数。