我们在使用Android静态加载so库的时候,一般都需要这个so库是符合jni命名规范的,像这样:
Java_全类名_方法名
但是可能会遇到一些比较特殊的情况,同事只给了你一个so库,这个so库并不是用的jni命名,除此之外,他还给了你一个so库中函数的头文件,这时候我们就需要自己再次包装这个so库了。
建立java文件
这里建立的java文件命名可以是自定义的,而不需要遵守某种规范,所在包名也没有讲究,因为这些都是我们需要自己包装的,所以可以随意些。
但是,需要注意的是,虽然说函数名字可以随意,但是我们一定得先想好函数的返回值,例如要头文件中函数返回的类型可能是int,但是我们希望在java中收到的是不是int,而是经过“二次加工”的其他值,这时候就应该把返回值设为其他类型,例如,在头文件中参数类型是char*, 如果我们使用java直接封装的话,返回值应该为char[],若我们还要二次封装,如要判断头文件中函数返回的char *是不是我们想要的字符,把判断结果返回,则可以自己任意定义返回值。
我们刚开始最需要关心的是头文件中定义的返回值并不是jni中已存在的类型,但是如果我们需要返回给java,则需要返回的是jni中定义的类型,这些类型有些是可以通过强制转换得到的,另一些则稍微麻烦,需要通过env提供的函数来进行转换。
具体可以参考下面的链接:
当然这之中也有可能会有特殊的情况,例如,若在cpp中返回的数据类型为void *,我们应该使用jlong返回给java。具体例子如下:
我在 com.example.jnitest.jnicontact 文件夹下建立了.java文件,具体代码如下:
package com.example.jnitest.jnicontact;
public class JniDefine {
public native int p2ptest(String localId);
public native long getp2psession(String remoteId);
}
根据编写的.java文件生成.h头文件
因为我们需要使用命令行来生成,