Android NDK项目中使用SWIG生成JAVA类和C/C++封装代码

转自:http://blog.csdn.net/koozxcv/article/details/50779806

发现最近记忆力非常差,估计和压力大有关系。今天在阅读《Android C++高级编程》这本书的时候,写了一个小的demo来利用SWIG工具来自动生成必要的JNI封装代码来简化

android c/c++项目的开发过程的 。在这里做个总结吧,和大家分享,也便于我今后忘记时快速回忆。毕竟好记性不如烂笔头!

1.什么是SWIG(Simplified Wrapper and Interface Generator)?

SWIG是一个编译时软件开发工具,它能生成将用C/C++编写的原生模块与包括Java在内(这里我们实际上只是验证了和java)编程语言进行关联的必要代码。

SWIG不仅是一个代码生成器,还是一个接口编译器。

SWIG把接口文件看做输入,并生成必要的代码,在Java中展示接口,从而让Java能够理解原生代码中接口的定义。

对于上面关于SWIG工具的介绍如果你感觉到生涩难懂,别着急,继续往下看,通过实例我想你会明白上面提到的“接口”,“C/C++封装”这些名词的含义的。

2.安装

ubuntu下安装很简单,因为我这里就是在ubuntu下安装的,因此就只介绍这一种环境下的安装:

[plain]  view plain  copy
  1. sudo apt-get install swig  

(哈哈,ubuntu下很简单吧!别的环境下,自行Google吧!)

3.试用SWIG

这一部分将通过一个具体的实例来介绍和试用SWIG。

我们要做一下几件事情:

写一个SWIG接口文件以向Java展示getuid函数;

将SWIG集成到Android构建过程中去;

将SWIG生成的源文件加入到Android.mk构建文件中;

用SWIG生成的代理类查询getuid函数;

在通过模拟器显示结果。

4.什么是接口文件?

SWIG接口文件包含函数原型、类、和变量的声明,它的语法和普通的C/C++头文件的语法是一样的。除了C/C++关键字和预处理指令,接口文件还包含SWIG特有的预处理指令。这些指令可用来优化生成封装代码。

步骤1:在工程的jni目录下新建一个文件,命名为Unix.i 。Unix.i就是接口文件,下面是Unix.i中的内容:

[python]  view plain  copy
  1. /*模块名*/  
  2. %module Unix  
  3. /*包含POSIX操作系统API*/  
  4. %{  
  5. #include<unistd.h>   
  6. %}  
  7. /*SWIG插入预处理指令的语法:  
  8. %< section >{  
  9. ...  
  10. 这个代码块将按照section的指定包含在生成代码的相应部分。  
  11. ...  
  12. %}  
  13. */  
  14. typedef unsigned int uid_t;  
  15.   
  16. /*让SWIG包装getuid函数*/  
  17. extern uid_t getuid(void);  

这里要说明的一点是,SWIG能理解C/C++的所有类型,但是会把其他的东西全部看成对象并把它们封装成指针。

uid_t并不是一个标准的C/C++类型,因此如果直接使用的话SWIG会将其当作对象封装成一个指针,显然不合适。

因此理由C/C++类型定义定义一下就可以了。

而最后一句,extern uid_t getuid(void);让SWIG来封装getuid函数,从而在java中展示。

5.命令行下调用SWIG

步骤1:创建Java代理包:在调用SWIG前先创建java代理类包目录,即在src下创建一个com.example.swig包。


步骤2:调用SWIG:在NDK工程目录下执行命令行:

[html]  view plain  copy
  1. swig -java -package com.example.swig -outdir src/com/example/swig  jni/Unix.i  
执行完之后,你就可以在jni目录下看到Unix_wrap.c,同时在com.example.swig包内生成Java代理类UnixJNI.java和Unix.java。


6.将SWIG集成到Android构建过程中

通过前面的步骤,我们能体会到,手动的使用SWIG非常繁琐,那么下面来看看如何将SWIG集成到Android构建过程中吧。

步骤1:创建my_swig_generate_mk文件,内容如下:

[python]  view plain  copy
  1. #  
  2. #@author andy  
  3. #  
  4. #检查变量MY_SWIG_PACKAGE是否已经定义  
  5. ifndef MY_SWIG_PACKAGE  
  6. $(error MY_SWIG_PACAGE is not defined.)  
  7. endif  
  8. #用斜杠替换java目录中的圆点  
  9. MY_SWIG_OUTDIR:=$(NDK_PROJECT_PATH)/src/$(subst .,/,$(MY_SWIG_PACKAGE))  
  10.   
  11. #设置SWIG模式  
  12. ifndef MY_SWIG_TYPE  
  13. MY_SWIG_TYPE:=c  
  14. endif  
  15. ifeq ($(MY_SWIG_TYPE),cxx)  
  16. MY_SWIG_MODE:=-c++  
  17. else  
  18. MY_SWIG_MODE:=  
  19. endif  
  20. #追加SWIG封装源文件  
  21. LOCAL_SRC_FILES+= $(foreach MY_SWIG_INTERFACE,\  
  22. $(MY_SWIG_INTERFACES),\  
  23. $(basename $(MY_SWIG_INTERFACE)))_wrap.$(MY_SWIG_TYPE)  
  24. #添加.cxx作为c++文件扩展名  
  25. LOCAL_CPP_EXTENISON+=.cxx  
  26. #生成SWIG封代码  
  27. %_wrap.$(MY_SWIG_TYPE):%.i  
  28.     $(call host-mkdir,$(MY_SWIG_OUTDIR))  
  29.     swig -java \  
  30.     $(MY_SWIG_MODE) \  
  31.     -package $(MY_SWIG_PACKAGE) \  
  32.     -outdir $(MY_SWIG_OUTDIR) \  
  33.     $<  
上面是源代码直接可以复制来用,但是看不到字体颜色,再附一副图片吧。


步骤2:将SWIG集成到Android.mk

打开Android.mk在如下位置添加代码:

[plain]  view plain  copy
  1. LOCAL_PATH := $(call my-dir)  
  2.   
  3. include $(CLEAR_VARS)  
  4.   
  5. LOCAL_MODULE    := hello-jni  
  6. LOCAL_SRC_FILES := hello-jni.c   
  7. MY_SWIG_PACKAGE:=com.example.swig  
  8. MY_SWIG_INTERFACES:= Unix.i  
  9. MY_SWIG_TYPE:=c  
  10. include $(LOCAL_PATH)/my_swig_generate.mk  
  11.       
  12. include $(BUILD_SHARED_LIBRARY)  

其中7-10行代码为添加代码。这一步操作要在共享库hello-jni.so生成之前。

步骤3:我们打开终端,在命令行下进入当前NDK工程目录,执行:

[plain]  view plain  copy
  1. ndk-build  
结果如下:

从终端输出我们能看到,生成的Unix_wrap.c(C封装代码,其中包含处理类型映射以及将选中的原生函数展示给Java的JNI封装函数)

如图:


7.修改并运行HelloJni工程

在Hellojni.Java文件中进行如下修改:

[java]  view plain  copy
  1. -- tv.setText(stringFromJNI());  
  2. ++ tv.setText("UID: "+Unix.getuid());  
在模拟器上运行应用程序Hellojni,可以看到下面结果:


8.总结:

开始写的时候还觉得要总结点什么,现在觉得好像学习的不够深入,所以就不总结了,以免误导大家,过一段时间深入学习了会更新blog,到时候再总结吧。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值