10、 JNI_Android项目中调用.so动态库

JNI_Android项目中调用.so动态库

2014年6月3日 JNI学习

参考:http://blog.sina.com.cn/s/blog_4298002e01013zk8.html

上一篇笔者介绍了如何使用Java代码调用DLL动态库中的C/C++方法,似乎已经是很久以前的做法了,遇到的错误笔者还未找到解决方案,但动态库着实是找到的,只是无法调用相应的方法。本篇博客来介绍一下如何在Android项目当中使用NDK生成.so动态链接库,并在程序中使用。

1. 在Eclipse中创建项目:TestJNI


2. 新创建一个class:TestJNI.java
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.wwj.jni;  
  2.   
  3. public class TestJNI {  
  4.     public native boolean Init();  
  5.     public native int Add(int x, int y);  
  6.     public native void Destory();  
  7. }  

以上代码声明三个本地方法。

3. 编译JNI
找到Android项目中bin目录下,会有classes文件夹,Eclipse自动为我们生成的字节码文件就在这个目录下。
我们在该路径下,使用javah命令,生成我们想要得到的.h头文件,如下图所示:


执行javah -jni com.wwj.jni.TestJNI命令之后,会在classes目录下生成头文件:com_wwj_jni_TestJNI.h
将它复制到jni文件夹下,打开如下:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>  
  3. /* Header for class com_wwj_jni_TestJNI */  
  4.   
  5. #ifndef _Included_com_wwj_jni_TestJNI  
  6. #define _Included_com_wwj_jni_TestJNI  
  7. #ifdef __cplusplus  
  8. extern "C" {  
  9. #endif  
  10. /* 
  11.  * Class:     com_wwj_jni_TestJNI 
  12.  * Method:    Init 
  13.  * Signature: ()Z 
  14.  */  
  15. JNIEXPORT jboolean JNICALL Java_com_wwj_jni_TestJNI_Init  
  16.   (JNIEnv *, jobject);  
  17.   
  18. /* 
  19.  * Class:     com_wwj_jni_TestJNI 
  20.  * Method:    Add 
  21.  * Signature: (II)I 
  22.  */  
  23. JNIEXPORT jint JNICALL Java_com_wwj_jni_TestJNI_Add  
  24.   (JNIEnv *, jobject, jint, jint);  
  25.   
  26. /* 
  27.  * Class:     com_wwj_jni_TestJNI 
  28.  * Method:    Destory 
  29.  * Signature: ()V 
  30.  */  
  31. JNIEXPORT void JNICALL Java_com_wwj_jni_TestJNI_Destory  
  32.   (JNIEnv *, jobject);  
  33.   
  34. #ifdef __cplusplus  
  35. }  
  36. #endif  
  37. #endif  

以上代码就是通过javah命令生成jni层代码。

4. 使用C/C++实现JNI
在jni文件夹下,创建com_wwj_jni_TestJNI.h对应的cpp文件:com_wwj_jni_TestJNI.cpp

我们再添加两个文件Add.h,Add.cpp,具体实现放在这两个文件中来完成。
Add.h
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef _TEST_JNI_ADD_H_  
  2. #define _TEST_JNI_ADD_H_  
  3.   
  4. class CAdd {  
  5. public:  
  6.     CAdd();  
  7.     ~CAdd();  
  8.   
  9.     int Add(int x, int y);  
  10. };  
  11.   
  12. #endif  


Add.cpp
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "Add.h"  
  2.   
  3. CAdd::CAdd() {  
  4.   
  5. }  
  6.   
  7. CAdd::~CAdd() {  
  8.   
  9. }  
  10.   
  11. int CAdd::Add(int x, int y) {  
  12.     return x + y;  
  13. }  


com_wwj_jni_TestJNI.cpp的实现:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include "com_wwj_jni_TestJNI.h"  
  4. #include "Add.h"  
  5.   
  6. CAdd *pCAdd = NULL;  
  7.   
  8. JNIEXPORT jboolean JNICALL Java_com_wwj_jni_TestJNI_Init(JNIEnv *env,  
  9.         jobject obj) {  
  10.     if (pCAdd == NULL) {  
  11.         pCAdd = new CAdd;  
  12.     }  
  13.     return pCAdd != NULL;  
  14. }  
  15.   
  16. JNIEXPORT jint JNICALL Java_com_wwj_jni_TestJNI_Add(JNIEnv *env, jobject obj,  
  17.         jint x, jint y) {  
  18.     int res = -1;  
  19.     if (pCAdd != NULL) {  
  20.         res = pCAdd->Add(x, y);  
  21.     }  
  22.     return res;  
  23. }  
  24.   
  25. JNIEXPORT void JNICALL Java_com_wwj_jni_TestJNI_Destory(JNIEnv *env, jobject obj)  
  26. {  
  27.     if (pCAdd != NULL)  
  28.     {  
  29.         pCAdd = NULL;  
  30.     }  
  31. }  


5. 创建mk文件,并使用ndk-build命令生成.so动态链接库文件
在jni目录下创建Android.mk文件如下:
[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. LOCAL_PATH := $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3.   
  4. LOCAL_MODULE := TestJNI  
  5.   
  6. LOCAL_SRC_FILES := com_wwj_jni_TestJNI.cpp  
  7. LOCAL_SRC_FILES += Add.cpp  
  8.   
  9. include $(BUILD_SHARED_LIBRARY)  

其中LOCAL_PATH是C/C++代码所在目录,也就是我们的jni目录。
LOCAL_MODULE是要编译的库的名称。编译器会自动在前面加上lib,在后面加上.so。
LOCAL_SRC_FILES是要编译的C/C++文件。

然后我还需要在Android项目根目录下创建Application.mk文件:
[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. APP_PROJECT_PATH := $(call my-dir)  
  2. APP_MODULES := TestJNI  

写完了这两个mk文件,我们就可以用ndk来为我们生成相应的动态链接库了。前提你需要下载NDK,并把NDK路径配置到path环境变量中去,笔者配置的路径是:D:\Cocos2dx\android-ndk-r9d,具体视个人情况而定。
进入Application.mk文件所在目录,在命令行中使用ndk-build生成.so文件



编译成功后会在工程目录的libs/armeabi目录下生成一个libTestJNI.so文件。

项目结构会变成如下:



6. 在Java中调用JNI
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.wwj.jni;  
  2.   
  3. import android.os.Bundle;  
  4. import android.widget.TextView;  
  5. import android.app.Activity;  
  6.   
  7. public class TestJNIActivity extends Activity {  
  8.   
  9.     private TextView textView;  
  10.     static {  
  11.         // 加载动态库  
  12.         System.loadLibrary("TestJNI");  
  13.     }  
  14.   
  15.     @Override  
  16.     protected void onCreate(Bundle savedInstanceState) {  
  17.         super.onCreate(savedInstanceState);  
  18.         setContentView(R.layout.activity_main);  
  19.         textView = (TextView) findViewById(R.id.textview);  
  20.   
  21.         TestJNI testJNI = new TestJNI();  
  22.         // 调用native方法  
  23.         boolean init = testJNI.Init();  
  24.         if (init == true) {  
  25.             // 调用Add函数  
  26.             int sum = testJNI.Add(100150);  
  27.             textView.setText("你真是个" + sum);  
  28.         } else {  
  29.             textView.setText("你比二百五还要二百五");  
  30.         }  
  31.         testJNI.Destory();  
  32.     }  
  33. }  



运行项目,效果图如下:




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值