Android Studio 下利用c语言生成so文件并利用jni调用(二))_android studio c语言环境-程序员宅基地

技术标签: c语言  Android Study  android  eclipse  

Android Studio 下利用jni生成编译C语言的so文件并调用的常见问题(二)

前言:
前几天记录了自己在AS下利用jni生成.so文件并调用的方法,成功的demo较为简单,不涉及过多头文件的开发,自己循着这个思路往下开发实时,遇到挺多问题,发现前一篇所提到的方法局限性太大,局限之处具体哪些请看接下来的问题描述。

平台环境与工具版本:
1、ubuntu18.04LTS
2、Android Studio Arctic For | 2020.3.1

赘述:
之前网络上的教程很多是在 eclipse 上开发,使用了最新Android Studio版本后,很少见到与自己相关的问题解决思路,所以一定注意版本不同很多语法已经变了,包括老版本Android Studio 和 eclipse 在jni开发时,使用javah xxx,但新版本AS用的是 javac -h xxx;当然你需要先在local.properties 里结合你自已ndk安装路径进行ndk.dir的配置。总之注意新旧版本的差异,遇到问题“考虑版本,非必要不死磕”!

问题(1)描述:

工程着涉及C的头文件<stdio.h> <string.h> ,在按住“Ctrl”点击鼠标左键时发现无法跳转,并出现了“cannot find declaration to go”的提示,如下图示,并且在使用两个头文件中的函数时发现确实是使用不了,提示“未定义”,那必然,跳转不过去你怎么找得到呢。

在这里插入图片描述

问题(1)解决思路一:

a. 首先百度了下,带着问题找了一些方法:江湖大佬们的解决办法都是重启、clear project、rebuild project, restart,对我当前的问题实在是没有帮助。你说你连库中的头文件都找不到,还怎么进行后续的编程,Android Arctic Fox更新到都无法在新建工程时都选择support C++了(除了Native C++方式构建project,“别抬杠哦”),这版本实在是不敢恭维。

b. 那就寻找下如何在建好的“普通工程(Empty Project)”中加入C++ support,遍历一圈,花了不少time,我没找到。于是想着上一篇,用empty project 构建生so,在Native C++ project中调用,难道逻辑不对?那难道应该Native C++ project 生成so ,在另外一个Native C++ project中调用,好,试试,就猜想这么干。

(具体怎么到下图所示这一步,我上一篇blog就有具体步骤,链接:https://blog.csdn.net/zxl970921/article/details/119711760?spm=1001.2014.3001.5501)本篇仅从此处开始“赘述”
在这里插入图片描述
同时在Test.c 中依然无法跳转,如下图
在这里插入图片描述

从图里看到:本以为只要在Native C++ project 下就无条件support C++ ,结果上来.h文件就爆红,而C文件依然找不到头文,比普通工程构建的还“傻”,我曾经“一度多次一键删除”(沈腾飞驰人生:我曾经跨过山河大海…),又新建继续研究,真是个磨人的过程。突然我头上飞过一只“xxx”,“哎,那为啥AS自主生成的native.cpp里的头文件就能自动跳转自动补全呢?“没错,你(native-lib.cpp)是亲儿子””一探究竟了,那必然来到了CMakeList.txt里查看,果然这有你,如下图

在这里插入图片描述
图中可以看了add_library 下有native-lib.cpp,恰好,亲儿子就在这,那我就顺势加一个,当然需要注意路径了,不然怎么找得到;如下图

在这里插入图片描述

add_library( # Sets the name of the library.
        netjni1
        # Sets the library as a shared library.
        SHARED
        ${CMAKE_SOURCE_DIR}/../jni
        # Provides a relative path to your source file(s).
        ${CMAKE_SOURCE_DIR}/../jni/Test2.c
        ${CMAKE_SOURCE_DIR}/../jni/Test.c
        native-lib.cpp)

这里就结合自身工程C文件路径来添加就行了。

到这一步还有个关键操作: 点击 File下的 Sync project with Gradle files 这样一来CMakeLists.txt 才会开始“生效”。

这样再去你的C文件和.h文件下 查看添加头文件就可以自动跳转和补全了。

问题(1)解决思路二:

a. 发人深思,解决问题的关键之处在于在CMakeLists.txt中修改添加,那么我好奇Empty Project 新建的工程里按照我前一篇blog方法步骤中添加一下是不是就OK了呢?问题来了:Empty Project中哪来的CMakeLists.txt?反正我没找到,没有那么咱就造一个,多大点事!

实操开始:
new 一个 Native C++ 将其cpp下的CMakelist.txt copy 过来,在本project /main、目录下新建一个cpp文件如图 ,将复制来的 CMakelist.txt Paste 过来。

在这里插入图片描述

此时必然会有新的风暴:CMakelist.txt文件呈现灰色,即没有作用,what?因为你没有在cpp下的build.gradle下指明CMakelist.txt的位置,必然找不到也就没用了,将以下代码添加在 cpp下的build.gradle的dependencies上方位置:

   externalNativeBuild {
    
        cmake {
    
        #请结合你自己的CMakelist.txt 路径来修改
            path file('src/main/cpp/CMakeLists.txt')
            version '3.10.2'
        }
    }
    buildFeatures {
    
        viewBinding true
    }

如下图(不带点图,可能像我一样的新手有点不适应)
在这里插入图片描述

到这一步还有个关键操作再次闪亮登场:
点击 File下的 Sync project with Gradle files 这样一来build.gradle和CMakeLists.txt 才会开始“生效”。这个时候CMakeLists.txt 就不再是“全灰色状态”回过去在CMakeLists.txt文件中 对应工程名之类的进行修改,修改为与当前的相符合,这个不在赘述,重点依然是添加add_library内容同上,即将.c文件的路径写入进行。

add_library( # Sets the name of the library.
        jnibili
        # Sets the library as a shared library.
        SHARED
        # Provides a relative path to your source file(s).
        ${CMAKE_SOURCE_DIR}/../jni
        ${CMAKE_SOURCE_DIR}/../jni/Test.c
        )

如下图
在这里插入图片描述
点击 File下的 Sync project with Gradle files。(总之:修改这两个文件后都需要这一步)

后续就可以愉快的在C文件中继续掉发了,支持c相关跳转和补全。

问题(2)描述:
在jni目录下执行 javac -h jni java/com/example/netjni1/Net.java
错误: 找不到文件: java/com/example/netjni1/Net.java
用法: javac <选项> <源文件>
使用 --help 可列出可能的选项

这个命令我近期天天用天天出错,主要原因“马大哈系列”

a. 检查你当前terminal路径,需要与你执行的对应起来,否则找不到文件

b. ndk.dir在local.properties中设置正确了没。

c. 新版本已经不再是javah 了,已经被javac 吞并了,注意正确用法。

参考了以下博主们的分享让我有了解决思路,感谢!

博客链接:

https://www.jianshu.com/p/92daab193195
https://blog.csdn.net/Xiongjiayo/article/details/85340121?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-11.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-11.control

以及bilibili学习链接:

https://www.bilibili.com/video/BV1HJ411L756?p=314&spm_id_from=pageDriver
https://www.bilibili.com/video/BV1qW411L7oY?p=39&spm_id_from=pageDriver

声明:

属于本人“小白小白小小白”原创,如果转需请注明出处。对于大佬来说这教程很儿科,但对于新手可能还是有帮助,为了顺应像我一样的新手,需要赘述太多,请大白们莫要见笑。

END !

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zxl970921/article/details/119925016

智能推荐

Sample Probability Space_probability space例题-程序员宅基地

文章浏览阅读66次。Sample Probability SpaceA simple probability space consist of a tuple (Ω\OmegaΩ,ε\varepsilonε,p)Ω\OmegaΩ is a finite set (with cardinality k= ∣\mid∣Ω\OmegaΩ∣\mid∣)ε\varepsilonε = { A : A ⊆\subseteq⊆ Ω\OmegaΩ } consist of all finite subsetsEach events _probability space例题

python分布式服务系统框架_Cola:一个分布式爬虫框架 - 系统架构 - Python4cn(news, jobs)...-程序员宅基地

文章浏览阅读348次。由于早先写的WeiboCrawler问题很多,而且当时我有提到,其实可以实现一个通用的爬虫框架。最近由于要抓取新的数据,于是我就写了这个cola。下面的文字来自wiki。Cola是一个分布式的爬虫框架,用户只需编写几个特定的函数,而无需关注分布式运行的细节。任务会自动分配到多台机器上,整个过程对用户是透明的。依赖由于Cola配置文件使用的yaml,所以Cola只依赖于pyyaml,安装easy_i..._cola爬虫

名悦集团国庆出行自驾游攻略-程序员宅基地

文章浏览阅读75次。在这个买车已经不是什么难事的年代,大多数人出行都会选择自驾方式,但自驾出游必然要面临一系列的问题以及做足准备工作。名悦集团小编给大家总结出了这次国庆假期出行自驾游攻略,为了保证自驾过程的安全顺利,玩得更加痛快,临行前的车辆检查时必不可少的,这些项目可以自己检查,如果实在是懒或者不懂,可以在临行前去4S店做个基础保养,以让爱车在最佳车况陪伴自己和家人朋友开始这段愉快的旅程。1.轮胎轮胎的检查是自驾前需要关键的检查之一,在自驾的旅程上不管是轮胎没气还是爆胎,都是非常令人揪心的,如果是在高速或者...

Android 输入法框架源码分析总结(1)_android 输入法源码-程序员宅基地

文章浏览阅读3.6k次,点赞3次,收藏7次。参考文档 https://blog.csdn.net/huangyabin001/article/details/28434989https://blog.csdn.net/huangyabin001/article/details/28435093#commentshttps://blog.csdn.net/jieqiong1/article/details/712629871..._android 输入法源码

Ubuntu下使用nnUNet 训练自己的数据集(只管实现,不讲原理,通俗易懂)_nnunet训练自己的数据集-程序员宅基地

本文介绍了如何在Ubuntu下使用nnUNet训练自己的数据集,不涉及原理解析,只提供实现步骤。包括nnUNet简介、修改训练参数和文件位置等操作。详细内容可参考Tina的博文。

SSM实现秒杀系统案例-程序员宅基地

文章浏览阅读9.9k次,点赞10次,收藏88次。对于抢购系统来说,首先要有可抢购的活动,而且这些活动具有促销性质,这种大型活动的负载可能是平时的几十倍,所以通过增加硬件、优化瓶颈代码等手段是很难达到目标的,所以抢购系统得专门设计。在这里我们说的库存不是真正意义上的库存,其实是该促销可以抢购的数量,真正的库存在基础库存服务。用户点击『提交订单』按钮后,在抢购系统中获取了资格后才去基础库存服务中扣减真正的库存;而抢购系统控制的就是资格/剩余数。传统方案利用数据库行锁,但是在促销高峰数据库压力过大导致服务不可用,目前采用redis集群(16分片)缓存促销信息,

随便推点

正则表达式匹配各种括号内内容_正则表达式 匹配多个括号-程序员宅基地

文章浏览阅读2.8w次,点赞10次,收藏9次。用正则表达式匹配两个字符中间的文本String skh ="(?<=\\《)[^\\》]+";//用于匹配《》里面的文本String str="但实际上《kajdwdej》孙大伟多";//测试字符串Pattern pattern=Pattern.compile(skh); Matcher matcher=pattern.matcher(str); boolean is=matche_正则表达式 匹配多个括号

Android 中的Shape_linear radial sweep分别代表的什么-程序员宅基地

文章浏览阅读553次。之前一直看项目用过这个东西,但是自己都不怎么熟悉,大概就知道可以画一些圆角之类的~ 今天就来好好了解一下吧~Shape里面有很多属性,依次学习一下第一步~首先来写一个Button这个布局文件就不贴了...太简单了~ (PS:说贴出来的站出来,我保证不打死你!)接下来开始学习第一个属性:Solid:(填充)在Drawable里面创建一个butt_linear radial sweep分别代表的什么

graphpad细胞增殖曲线_如何用GraphPad Prism绘制剂量反应曲线?-程序员宅基地

文章浏览阅读6.1k次。上图是Sci文献中的dose–response curves (剂量反应曲线),横坐标是药物GS-Se-SG浓度的对数值,纵坐标是Rrelative cell viability(相对细胞活性,% of control),从图注中可以知道IC50为5.1 μM。那么什么是IC50呢?IC50 (half maximal inhibitory concentration)是指被测量的拮抗剂的半抑制浓..._graphpad细胞增殖曲线

二叉查找树(非递归、递归遍历)_二叉排序树非递归查找-程序员宅基地

文章浏览阅读658次。二叉查找树(含递归、非递归遍历)_二叉排序树非递归查找

spark-sql 查询报错:Invalid method name: ‘get_table_req‘_invalid method name: 'get_table_req-程序员宅基地

文章浏览阅读3.1k次。spark-sql> select * from zps_d001 limit 1;Error in query: org.apache.hadoop.hive.ql.metadata.HiveException: Unable to fetch table zps_xxx. Invalid method name: 'get_table_req'org.apache.spark.sql.AnalysisException: org.apache.hadoop.hive.ql.metadata.H_invalid method name: 'get_table_req

unknown mutation type:-程序员宅基地

文章浏览阅读1.7w次。我这边使用得是vue+elementvue得状态组成actions 这个是异步请求 通过异步请求得话 然后在调用 mutations.jsmutations.js 将数据提交到这里 this.$commit(‘test’,testTemp)index.js 这个是将数据初始化getters 这个是将 this.$store.getters.test 就能获取到了 testTemp写法是这个写法最后得原因是因为我这在 index.js 和mutation.js 为定义常量##_unknown mutation type

推荐文章

热门文章

相关标签