AndroidStudio最新版(2021.1.21)编译C++代码生成so文件

663 阅读4分钟

「这是我参与2022首次更文挑战的第29天,活动详情查看:2022首次更文挑战」。

上一章节介绍了如何配置so文件需要的开发环境,今天这一章节主要介绍,如何将C++代码编译成so文件。

看过我之前文章的都知道,其实我是一个地地道道的C++开发程序猿,因为同事离职,他负责的so文件编译的重担就放到了我身上,责任重大呀!

今天我就来讲解下我是如何一步一步以C++开发程序员的角度创建并调用so文件的,适合跟我一样的小白。

java环境与Android环境上一章节中有介绍,这里不再过多说明了。

1:创建so文件的工程

新建so工程.png

按照图片指示,创建一个新工程,此时会出现以下这个界面

选择新建工程类型.png

选择最后一个:Native C++

C++工程.png

点击下一步之后出现下图页面

编辑工程.png

页面说明:

Name:项目名称,这个随意声明。

Package name:包名称。

其实我刚开始做的时候以为这个名称就是固定的,结果,后来才发现,这是可以修改的,简直了!!

配置好该页面后,直接点击右下角的“Finish”,项目就算建好了。

建好的项目.png

如果是这样的,说明项目跟我建立的是一致的。记得需要用Project查看才是这样的。

在开发过程中,安卓想要调用C++代码是不能直接调用的,这时,就需要一个中间键来通信,在上述图片汇总,“native-lib.cpp”这就是两个不同平台的中间键代码,编译的最终so文件也是调用的"native-lib.cpp"中的函数内容。

默认的native-lib内容如下:

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_st_hellworld_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

刚开始看到这个文件的时候,我简直都懵了,怎么会有这么长的函数名,这个函数名这么定义有什么意义呢?

研究了好长时间我才知道,Android调用还真是挺严谨的!

函数名:Java_com_st_hellworld_MainActivity_stringFromJNI进行讲解

图片.png

看到图片上用蓝色框出来的区域,这是这个调用函数的函数名的意思,是在java文件夹下,com文件夹下,st文件夹下,helloworld文件夹下的MainActivity类中的 stringFromJNI函数的中间键说明。

那么,我们来看一下MainActivity文件

MainActivity.png

想要哪个函数与C++通信,那么哪个函数前面就需要有"native"字样表示。

在图片中蓝色区域选中的stringFromJNI函数是需要生成so文件被调用的。

2:编译so文件

build.png

选中Make Project直接编译"Hello World"项目,编译完成之后会在app中出现一个build文件,如图所示

build完成.png

蓝色区域内就是生成的so的位置。

到这里,不改变任何代码就可以直接生成简单的so文件。

3:使用so文件

上述编译完成后,接下来是该如何使用编译好的so文件。

3.1:创建一个新Android Studio项目

新建安卓项目.png

这里,选中"Empty Activity"类型创建项目,名称随意定义,假设叫做:UseAndroidTest1

3.2:项目中配置so文件

第一步

在app->src->main中创建一个叫做:jniLibs文件夹,这里存放的是 cmake编译的so文件,如图所示

新项目配置solib.png

第二步

修改app文件夹下的"build.gradle",改成如图所示内容

buildGradlepng.png

此时,so文件所需的内容就已经配置完成了,

3.3:调用so文件中的API

这也是最最容易出错,也是最不容易发现错误的地方了。

在中间键文件:native-lib.cpp中,有一个默认的函数,函数名是:Java_com_st_hellworld_MainActivity_stringFromJNI

当我们在调用so的位置也需要按照so中函数名的方式创建一个一模一样的路径,并且类名叫做:MainActivity,有一个叫做stringFromJNI的函数,只有这样才会调用成功。

在st下面创建一个与so函数中层级一样的文件夹

挪动文件.png

只有这样将,在helloword中MainActivity调用stringFromJNI函数才会成功,否则会出错!

我是中国好公民st,一名C++开发程序猿~