• <Android开发> HAL层集成第三方so库


    Android开发> 集成so库
    上述文章是对本文的补充。

    当我们需要在自己的代码中使用第三方提供的一些接口函数时,我们该如何加入?作者在写这比安文章前遇到了一个问题:需要在自己的HAL层中引用第三饭提供的算法库即so库;这个问题是作者第一次遇到,以往都是自己写一些代码编一些so,然后引用的。对于这个问题,作者也问了度娘,但搜索到的方法各式各样,且有些还是FW层 或app层的一些方法。这里作者对所使用的方法进行了一些总结。

    一、问题前提
    作者需要在HAL层(HIDL服务) 引用第三方so库;

    二、第三方提供资料
    第三方提供的资料包含 : .so 文件 和 .h文件;

    三、添加SO编译
    这里作者当前模块是使用Android.mk 进行编译的; 需要在mk文件中引入第三方so进行编译。这里作者尝试了几种方法,读者根据自身条件或可行性进行使用测试。
    方法1: 将第三方so编译成本地so。
    添加编译方式在mk中添加内容如下:

    include $(CLEAR_VARS)
    LOCAL_MODULE := libwater 
    LOCAL_SRC_FILES :=$(LOCAL_PATH)/lib64/libwater.so
    LOCAL_MULTILIB := 64
    LOCAL_MODULE_CLASS := SHARED_LIBRARIES
    LOCAL_MODULE_SUFFIX := .so
    LOCAL_PROPRIETARY_MODULE := false
    LOCAL_MODULE_PATH := $(TARGET_OUT)/lib
    LOCAL_MODULE_TAGS := optional
    include $(BUILD_PREBUILT)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    第1行:清理编译变量;
    第2行:编译生成的目标文件名,这里就是需要生成的库名;
    第3行:编译所使用的源文件,可以是.so,或.cpp等源文件;
    第4行:声明生成64位 或32位库;
    第5行:声明模块是 共享库的形式;
    第6行:so的形式;
    第7行:是否专有模块,false:否
    第8行:输出目标的路径,这个可以自定义,一般是放到“vendor/lib” 或“vendor/lib64”;
    原因是:编译打包时,会将so 一起打包进vendor.img,后续引用就不会提示找不到; 或者测试时可手动 adb push;
    第9行:目标标记;
    第10行:生成目标的类型。

    注意:

    1. 如果有多个so,需要分别生成对应的so;
    2. 多个so之间,不可相互依赖;
    3. 如果多个so之间有相互依赖,需要分别添加引用到 对应so编译的mk中。
    4. 编译so部分一般建议放到mk的文件前部分。

    将编译生成的so,添加到引用模块的 “LOCAL_SHARED_LIBRARIES” 中;如:

     LOCAL_SHARED_LIBRARIES += \
     								libwater 
    
    • 1
    • 2

    方法2:使用 LOCAL_LDFLAGS 参数编译带-L 和-l参数

    在需要引用的模块中添加下面语句:

    LOCAL_LDFLAGS := -L./lib64/ -lwater
    
    • 1

    -L:表示so库所在路径位置;
    -l:表示so库名,不带前缀lib 和 后缀.so;

    方法3:使用 LOCAL_LDFLAGS 不带参数
    在需要引用的模块中添加下面语句:

    LOCAL_LDFLAGS += LOCAL_LDFLAGS += $(LOCAL_PATH)/lib64/libwater.so
    
    • 1

    直接引用so库,如有多个 可分行重复语句书写。

    四、头文件引用
    在引用SO编译的位置添加i安眠语句:

    LOCAL_C_INCLUDES += \
    			./include
    
    • 1
    • 2

    五、编译
    编译前提android源码需要整编过一次;
    进入android源码根目录运行下面命令:

    		source build/envsetup.sh
    		lunch xxx
    
    • 1
    • 2
    然后进入到需要编译的模块目录下,运行:
    
    • 1
    mma
    或
    mm
    或
    mmm
    
    • 1
    • 2
    • 3
    • 4
    • 5

    六、接口调用测试
    在需要调用的的cpp源码中,添加 头文件引用;
    如: #include “water.h”
    在添加接口调用,如:
    int ret = waterstart();

    七、编译出错
    错误1:如果编译时提示的错误如下图:

    在这里插入图片描述
    解决方法:由于引用的时第三方64位so,系统可能默认对第三方库使用32位进行编译,所以会提示架构不同; 需要在引用so之前添加一句“LOCAL_MULTILIB := 64”,声明时64位,即可。

    八、验证
    编译成功后可看到 输出的路径位置;
    使用adb push命令将文件放到vendor/bin/hw目录下,重启设备运行;
    查看输出的log即可。

    补充说明:
    补充1: 当引用的so库存在在system目录下,但是需要引用的确需在vendor目录下时;可通过预编译的形式;
    编写Android.bp文件,以libstdc++.so为例,增加下面内容:

    cc_prebuilt_library_shared {
        name: "libstdc++_dr",
        stem: "libstdc++",
        vendor: true,
        multilib: {
            lib64: {
                srcs: ["lib64/libstdc++.so"],
            },
        },
        check_elf_files: false,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    如果是引用第3方so的,也可使用预编译这一方法。

  • 相关阅读:
    Linux 文件系统逻辑结构图的解释
    排序算法(Python实现)
    Android12版本闹钟服务崩溃问题
    Kubernetes(K8s):未来云原生应用的引擎
    mysql存储过程
    全局下载报错怎么办
    CSS transform
    go语言切片的用法
    C#使用WebSocket与网页实时通信
    IO流{文件和目录 File 字符如何储存在电脑上 字节输入流 字节输出流 read方法读的字节为什么返回int类型}(一)
  • 原文地址:https://blog.csdn.net/qq_39257814/article/details/128073739