Android Studio引入ndk编译的so库, 通过jni给Java程序使用

前言

工作要求将一个C++老项目的函数用ndk打包成库给安卓同事的java程序调用。

这个任务我debuff拉满:

  • 自己之前从来没接触过安卓开发,问了老板为什么不让安卓开发来干,老板说安卓开发不懂c++,公司就我一个是懂c++的。。。
  • 项目开发年限超过十年,只在32位系统编译过,一些32位可以通过的代码到了64位就不行了,很多的库多少有些兼容问题
  • 项目开发环境全程断网,给开发带来诸多不便

感谢智谱和GPT4,最后花了几天还是摸清了一条路出来,不然可能过了一周都搞不清android.mk要怎么写。

不废话,笔记如下:

知识点记录:
NDK:Native Development Kit,是 Android 的一个工具开发包。NDK 可以看做是 Android 中实现 JNI 的一种手段(另一种是CMake),通过 NDK,还可以打包 C/C++ 动态库,并自动打包进 APK/AAR 中。我们可以到安卓官网下载NDK,可以直接执行NDK命令,也可以集成NDK到AndroidStudio中编译C/C++文件。

JNI:Java Native Interface,即 Java 本地接口。使得 Java 与本地其他类型语言(如 C、C++)交互。也就是在 Java 中调用 C/C++ 代码,或者在 C/C++ 中调用 Java 代码。JNI 是 Java 的,和 Android 无关。
.SO文件:so文件是Linux下的程序函数库,即编译好的可以供其他程序使用的代码和数据。一般来说.so文件就是常说的动态链接库, 都是C或C++编译出来的。与Java比较就是:它通常是用的Class文件(字节码)。Linux下的.so文件时不能直接运行的,一般来讲,.so文件称为共享库。

Android.mk :文件位于项目 jni/ 目录的子目录中,用于向编译系统描述源文件和共享库。它实际上是编译系统解析一次或多次的微小 GNU makefile 片段。Android.mk 文件用于定义 Application.mk、编译系统和环境变量所未定义的项目范围设置。它还可替换特定模块的项目范围设置。Android.mk 的语法支持将源文件分组为模块。模块是静态库、共享库或独立的可执行文件。

开发环境

OS:Windows 11

Android Studio版本:2021.3.1.17 Download link

NDK: r26d download link

开始操作

编译安卓so库

首先得搞清楚ndk-build怎么使用,这东西本质是对clang的封装, android.mk就相当于ndk的makefile,这里用一个c++的四则运算来讲。

创建这么个项目:

PS D:\MyCodeBase\ndk_test> ls
目录: D:\MyCodeBase\ndk_test

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         2024/7/13     17:34            594 android.mk
-a----         2024/7/13     17:29             71 application.mk
-a----         2024/7/13     17:27            838 mycal.cpp
-a----         2024/7/13     17:27            520 mycal.h

c++的四则运算类实现如下,我这里参考公司的实现方式,一个亮点是使用了工厂模式,头文件类只放基类,基类内全是纯虚函数(接口),实现在源文件里另有子类处理,头文件只提供creator创建实现类,返回基类指针,通过基类指针来操作接口方法。

// mycal.h

#ifndef MYCAL_H
#define MYCAL_H

#include <iostream>
#include <string>

// 运算接口基类
class Calculator {
   
   
public:
    virtual ~Calculator() = default;

    virtual double add(double a, double b) const = 0;
    virtual double sub(double a, double b) const = 0;
    virtual double mul(double a, double b) const = 0;
    virtual double div(double a, double b) const = 0;
};

// 非类成员工厂函数声明
Calculator* createCalculator();

#endif // MYCAL_H
// mycal.cpp

#include "mycal.h"
#include <stdexcept>

// 实现Calculator接口的具体类
class CalculatorImpl : public Calculator {
   
   
public:
    double add(double a, double b) const override {
   
   
        return a + b;
    }

    double sub(double a, double b) const override {
   
   
        return a - b;
    }

    double mul(double a, double b) const override {
   
   
        return a * b;
    }

    double div(double a, double b) const overrid
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值