技术标签: c语言 Android Study android eclipse
前言:
前几天记录了自己在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
属于本人“小白小白小小白”原创,如果转需请注明出处。对于大佬来说这教程很儿科,但对于新手可能还是有帮助,为了顺应像我一样的新手,需要赘述太多,请大白们莫要见笑。
文章浏览阅读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例题
文章浏览阅读348次。由于早先写的WeiboCrawler问题很多,而且当时我有提到,其实可以实现一个通用的爬虫框架。最近由于要抓取新的数据,于是我就写了这个cola。下面的文字来自wiki。Cola是一个分布式的爬虫框架,用户只需编写几个特定的函数,而无需关注分布式运行的细节。任务会自动分配到多台机器上,整个过程对用户是透明的。依赖由于Cola配置文件使用的yaml,所以Cola只依赖于pyyaml,安装easy_i..._cola爬虫
文章浏览阅读75次。在这个买车已经不是什么难事的年代,大多数人出行都会选择自驾方式,但自驾出游必然要面临一系列的问题以及做足准备工作。名悦集团小编给大家总结出了这次国庆假期出行自驾游攻略,为了保证自驾过程的安全顺利,玩得更加痛快,临行前的车辆检查时必不可少的,这些项目可以自己检查,如果实在是懒或者不懂,可以在临行前去4S店做个基础保养,以让爱车在最佳车况陪伴自己和家人朋友开始这段愉快的旅程。1.轮胎轮胎的检查是自驾前需要关键的检查之一,在自驾的旅程上不管是轮胎没气还是爆胎,都是非常令人揪心的,如果是在高速或者...
文章浏览阅读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简介、修改训练参数和文件位置等操作。详细内容可参考Tina的博文。
文章浏览阅读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_正则表达式 匹配多个括号
文章浏览阅读553次。之前一直看项目用过这个东西,但是自己都不怎么熟悉,大概就知道可以画一些圆角之类的~ 今天就来好好了解一下吧~Shape里面有很多属性,依次学习一下第一步~首先来写一个Button这个布局文件就不贴了...太简单了~ (PS:说贴出来的站出来,我保证不打死你!)接下来开始学习第一个属性:Solid:(填充)在Drawable里面创建一个butt_linear radial sweep分别代表的什么
文章浏览阅读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次。二叉查找树(含递归、非递归遍历)_二叉排序树非递归查找
文章浏览阅读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
文章浏览阅读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