Android C_Demo - 使用NDK编译C代码并生成可执行文件

        弹指一挥间,已经工作了两三年,期间一直想用博客记录自己工作中碰到的问题或学到的东西,结果一直都是拖拖拖。刚好趁最近在温习C语言,便正式开启博客生涯。(Ps. 写完后发现,这文章风格像是在写实训报告啊)

        废话不多说,本文主要讲使用NDK编译一个用C写的小demo,放在Android平台上通过命令行调用。(如果要生成可以通过Java代码直接调用的so库,c代码的入口不能是main(),需要按包名改,如:JNIEXPORT jint JNICALL Java_com_example_jnitest_MainActivity_main() )

    准备工作:

    1.下载并安装好了NDK,且将其添加进环境变量,这样就可以交叉编译,生成能在Android平台运行的二进制文件了;

    2.准备c源码和NDK编译用的Application.mk和Android.mk文件(如果要编辑c代码,习惯了Android Studio的风格,肯定推荐同一家出品的CLion):

    C源码(文件名为 count.c):

#include 
#include 
#include 
#include 

int count = 0;
int num = 10;//默认参数10
int ic;

void printText(int number) {
    char *str = "count";
    printf("%s %d\n", str, number);
}

int main(int argc, char *argv[]) {
    while ((ic=getopt(argc, argv, "c::")) != -1) {
        switch (ic) {
            case 'c':
                num = atoi(optarg);
                printf("获取参数num=%d\n", num);
                break;
            default:
                num = 10;
                printf("设置默认参数num=%d\n", num);
                break;
        }
    }
    printf("执行参数num=%d\n", num);
    while (true) {
        printText(count);
        count++;
        if (count >= num) {
            return 0;
        } else {
            sleep(1);
        }
    }
}

    Android.mk文件内容:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := count.c
LOCAL_MODULE := count
include $(BUILD_EXECUTABLE)

 Application.mk文件内容:

APP_PLATFORM := android-19
APP_ABI := armeabi-v7a
APP_OPTIM := debug

        准备工作好了,接下来就要使用“ndk-build”命令来交叉编译了,使用“ndk-build”命令对目录名字有特殊要求,必须要在android工程的app\src\main底下的jni文件夹层级里使用,android工程里默认没有jni文件夹,需要自己创建,如下图1-1所示:

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第1张图片

图1-1

    然后把c源码(count.c)、Android.mk文件和Application.mk文件放入jni文件夹,如下图1-2所示:

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第2张图片

图1-2

 在jni目录空白处按住shift键右击,即可快速调出cmd并把目录定位到jni,如图1-3和1-4所示:

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第3张图片

图1-3

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第4张图片

图1-4

        接下来在命令行里输入ndk-build命令,如果环境配置正确,输出如图1-5所示:(编译当中提示非法字符可忽略,因为c源码里有汉字,为了在android平台输出不乱码,我把文件编码改成GB2312,而NDK编译默认使用的是UTF-8,所以编译时会有提示,文章后面会详细说明怎么在CLion里改文件编码)

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第5张图片

图1-5

    如果结果如图1-5,则说明已经交叉编译好了,你会注意到main文件夹底下多了libs文件夹和obj文件夹,我们要的可执行文件在libs\armeabi-v7a文件夹里面,如图1-6所示:

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第6张图片

图1-6

    可执行文件已经生成好了,接下来就要把文件放入到Android平台。首先确保Android设备已经连上电脑,并且通过adb连接调试,接下来就是通过adb命令把文件放进去,如图1-7所示(adb命令为:adb  push  count  /data/local/tmp):

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第7张图片

图1-7

        至于为什么放在/data/local/tmp目录下,因为这个目录有文件执行权限,如果放在/sdcard目录下,是没有执行权限的。(当然你也可以放到/system/bin目录下,Android里的系统工具都在这里面,不过你是没有写入权限的,除非对/system分区重新挂载)

        接下来我们要看看count可执行文件有没有执行权限,首先打开命令行,输入命令adb shell,即可成功连上Android设备,如图1-8所示:


图1-8

        接下来定位到/data/local/tmp目录,输入命令cd /data/local/tmp,之后再输入命令ll来查看目录下所有文件的权限,如图1-9所示:

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第8张图片

图1-9

        从图1-9中看到,count文件只有读写权限,没有执行权限,接下来给它添加执行权限,输入命令chmod 777 count,然后再次输入命令ll查看文件权限,如图1-10所示:

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第9张图片

图1-10

        从图1-10中看到,count文件已经有可执行的权限了,接下来就可以通过命令./count -c7 来执行文件了(-c7即设置参数,显示7次),如图1-11所示:

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第10张图片

图1-11

        至此,整个流程跑通了。不过还有一个问题,就是之前提到的汉字乱码问题,为了不乱码,需要通过CLion修改编码,如图1-12和1-13所示,在CLion界面右下角点击GBK,点击编码类型中的GB2312,点击转换按钮后,即可把当前文件编码由GBK转换成GB2312。

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第11张图片

图1-12

Android C_Demo - 使用NDK编译C代码并生成可执行文件_第12张图片

图1-13

        最后说一下相关编码,如果想要在android平台输出不乱码,需要把文件编码改成GB2312,如果想要在CLion调试输出不乱码(windows平台),需要把文件编码改成GBK,而想要NDK编译时不提示非法默字符,则需要使用UTF-8。




参考文章:

https://blog.csdn.net/qq_30135181/article/details/53206563

https://blog.csdn.net/Cbk_XLL/article/details/78752534


你可能感兴趣的:(Android C_Demo - 使用NDK编译C代码并生成可执行文件)