android studio cmake生成.a文件(静态库)及调用(c c++)静态库.a

第一步生成静态库.a文件:

cmake 语法如何生成静态库,就不介绍了,比较简单,我下文列出的参考资料里面有详细介绍。

java 复制代码
add_library(${CMAKE_PROJECT_NAME} STATIC
         src/CalculStatic.cpp
        )

这一步有坑,我刚开始的时候,也花了不少时间,死活都没有生成.a静态库文件。但是我多方查找资料,发现是可以生成静态库文件的。关键是要配置"targets" 。这个属性只有在" defaultConfig" 下面才能配置出来,在大括号"android "下面配置的"cmake "是没有"targets"这个属性的,我就是因为在此耽搁了不少时间。一定要谨慎。

参考资料:https://stackoverflow.com/questions/64829357/specify-targets-in-externalnativebuild-of-the-build-gradle-file-no-signature-o

正确的build.gradle配置如下:

c 复制代码
android {

    defaultConfig {
        :
        externalNativeBuild {
            cmake {
               targets "calStatic" // New line here!
            }
        }
    }

    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
            // targets "native-lib"  // Not here!
        }
    }
}

重新运行项目或者"Make Project". 重新刷新目录,静态库.a文件就可以正确生成了。

参考资料:
android studio生成静态库没有*.a目标文件问题
android studio 3.2 使用cmake在jni生成及使用C/C++静态库

第二步使用静态库.a文件:

限制我们需要来调用我们刚刚生成的静态库.a文件

CMakeLists.txt

c 复制代码
cmake_minimum_required(VERSION 3.22.1)

project("cmake")

add_library(${CMAKE_PROJECT_NAME} SHARED
            native-lib.cpp
            src/libtest.c
        )

#导入已经编译好的静态库 或者 动态库  本例导入的静态库
add_library(calStatic STATIC IMPORTED)
#设置静态库导入的路径
set_target_properties(calStatic PROPERTIES IMPORTED_LOCATION
        ${CMAKE_CURRENT_SOURCE_DIR}/jni/${CMAKE_ANDROID_ARCH_ABI}/libcalStatic.a
)

#通过target_link_libraries命令指明库文件,且通过target_include_directories命令指明相应的库头文件
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include/static/)
#需要链接或者编译的库
target_link_libraries(${CMAKE_PROJECT_NAME}
        # List libraries link to the target library
        android
        calStatic
        log)

native-lib.cpp

c 复制代码
#include "CalculStatic.h"

  //调用了libcalStatic.a静态库中的方法
 jint addSum(JNIEnv *env,jobject instance,jint a,jint b,jint c){ //调用静态库
  return  calculAdd(a,b,c);
 
//动态注册
jint RegisterNatives(JNIEnv *env) {
    jclass clazz = env->FindClass("com/gitbaike/cmake/MainActivity");
    if (clazz == NULL) {
        LOGE("con't find class: com/gitbaike/cmake/MainActivity");
        return JNI_ERR;
    }
    JNINativeMethod methods_MainActivity[] = {
            {"stringFromJNI", "()Ljava/lang/String;", (void *) stringFromJNI},
            {"add",           "(II)I",                (void *) add},
            {"changePersonName", "(Lcom/gitbaike/cmake/model/Person;)V",(void *) changeName},
            {"getPerson", "()Lcom/gitbaike/cmake/model/Person;",(void *)getNewPerson},
            {"getPeronList", "()Ljava/util/List;",(void *) getListPerson},
            {"addSum", "(III)I",(void *)addSum}
    };
    // int len = sizeof(methods_MainActivity) / sizeof(methods_MainActivity[0]);
    return env->RegisterNatives(clazz, methods_MainActivity,
                                sizeof(methods_MainActivity) / sizeof(methods_MainActivity[0]));
}

jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }
    jint result = RegisterNatives(env);
    LOGD("RegisterNatives result: %d", result);
    return JNI_VERSION_1_6;
}

Java端调用:

c 复制代码
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    // Used to load the 'cmake' library on application startup.
    static {
        System.loadLibrary("cmake");
    }

    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

//         Example of a call to a native method
        TextView tv = binding.sampleText;
        tv.setText(stringFromJNI());

        HNPCInit();

        Person person=new Person();
        person.setAge(12);
        person.setName("java person");

        Log.d(TAG,"调用本地方法前: person.getName:"+person.getName());
        changePersonName(person);
        Log.d(TAG,"调用本地方法后: person.getName:"+person.getName());

        Person nPerson=getPerson();
        Log.d(TAG,"调用本地方法 getPerson()后: person:"+nPerson.toString());

        List<Person> personList=getPeronList();
        Log.d(TAG,"调用本地方法 getPerson()后: personList:"+new Gson().toJson(personList) );

        Log.d(TAG,"调用本地方法 addSum:"+addSum(10,15,65));
    }

    /**
     * A native method that is implemented by the 'cmake' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();

    public native void HNPCInit();

    public native int add(int a,int b);

    public  native void changePersonName(Person mPerson);

    public native Person getPerson();

    public native List<Person> getPeronList();

    private native int addSum(int a,int b,int c);
}

运行结果:

相关推荐
看到我,请让我去学习15 分钟前
OpenCV编程- (图像基础处理:噪声、滤波、直方图与边缘检测)
c语言·c++·人工智能·opencv·计算机视觉
倔强的小石头_2 小时前
【C语言指南】函数指针深度解析
java·c语言·算法
软件工程师文艺8 小时前
解决Android Studio不能同时打开多个文件问题
android studio
花花鱼8 小时前
android studio 设置让开发更加的方便,比如可以查看变量的类型,参数的名称等等
android·ide·android studio
jz_ddk8 小时前
[学习] C语言数学库函数背后的故事:`double erf(double x)`
c语言·开发语言·学习
xiaolang_8616_wjl9 小时前
c++文字游戏_闯关打怪2.0(开源)
开发语言·c++·开源
夜月yeyue9 小时前
设计模式分析
linux·c++·stm32·单片机·嵌入式硬件
无小道9 小时前
c++-引用(包括完美转发,移动构造,万能引用)
c语言·开发语言·汇编·c++
FirstFrost --sy11 小时前
数据结构之二叉树
c语言·数据结构·c++·算法·链表·深度优先·广度优先
森焱森11 小时前
垂起固定翼无人机介绍
c语言·单片机·算法·架构·无人机