下的所有 .cpp/.c 文件,这时候 wildcard
来统配会很方便。但是 Android.mk 与普通的 Makefile 不同在于:
- 调用 Android.mkmingling 的 ${CWD} 并不是 Android.ml 所在的目录。所以 Android.mk 中有一个变量
LOCAL_PATH := $(call my-dir)
来记录当前 Android.mk 所在的目录。
- 同时还会把所有的
LOCAL_SRC_FILES
前面加上 $(LOCAL_PATH)。
这样写 makefile 的时候就可以用相对路径了,提供了方便。但是这也导致了坑!
因为1,直接使用相对路径会导致wildcard
匹配不到源文件。所以最好这么写 FILE_LIST := $(wildcard $(LOCAL_PATH)/soundtouch_source/source/SoundTouch/*.cpp)
。然而又因为2,这样还是不行的。所以还需要匹配之后把$(LOCAL_PATH)
的部分去掉,因此还得这样 $(FILE_LIST:$(LOCAL_PATH)/%=%)
.
还有个小tip:LOCAL_CFLAGS
中最好加上这个定义 -fvisibility=hidden
这样就不会在动态库中导出不必要的函数了。
附录签名
Java 中的函数签名包括了函数的参数类型,返回值类型。因此即使是重载了的函数,其函数签名也不一样。java编译器就会根据函数签名来判断你调用的到地址哪个方法。 签名中表示类型是这样的
1.基本类型都对应一个大写字母,如下:
2. 如果是类则是: L + 类全名(报名中的点(.)用(/)代替)+ ; 比如java.lang.String 对应的是 Ljava/lang/String;
3. 如果是数组,则在前面加[
然后加类型签名,几位数组就加几个[
比如int[]对应[I
,boolean[][] 对应 [[Z
,java.lang.Class[]对应[Ljava/lang/Class;
可以通过 javap 命令来获取签名(javah 生成的头文件注释中也有签名):javap -x -p <类全名>
坑爹的是java中并不能通过反射来获取方法签名,需要自己写一个帮助类。 (其实我还写了个小程序可以自动生成签名,和 JNI_OnLoad 中注册要用到的 JNINativeMethod
数组,从此再也不用糟心的去写那该死的数组了。LOL~~~)
参考资料
- Oracle Java SE documents
- 深入理解Android 卷 1 第二章 ,邓凡平著,机械工业出版社
- Google Android documents – JNI Tips