惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
The GitHub Blog
The GitHub Blog
美团技术团队
Security Latest
Security Latest
The Cloudflare Blog
D
DataBreaches.Net
Microsoft Azure Blog
Microsoft Azure Blog
V
Visual Studio Blog
宝玉的分享
宝玉的分享
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
The Exploit Database - CXSecurity.com
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
P
Proofpoint News Feed
V
Vulnerabilities – Threatpost
Schneier on Security
Schneier on Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
Security Affairs
腾讯CDC
H
Hacker News: Front Page
Microsoft Security Blog
Microsoft Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 三生石上(FineUI控件)
C
Check Point Blog
S
Security @ Cisco Blogs
Google DeepMind News
Google DeepMind News
Cisco Talos Blog
Cisco Talos Blog
云风的 BLOG
云风的 BLOG
M
MIT News - Artificial intelligence
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Security Archives - TechRepublic
Security Archives - TechRepublic
I
InfoQ
量子位
Apple Machine Learning Research
Apple Machine Learning Research
AWS News Blog
AWS News Blog
TaoSecurity Blog
TaoSecurity Blog
月光博客
月光博客
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
aimingoo的专栏
aimingoo的专栏
S
SegmentFault 最新的问题
A
Arctic Wolf
Hacker News: Ask HN
Hacker News: Ask HN
D
Docker
Hugging Face - Blog
Hugging Face - Blog
I
Intezer
雷峰网
雷峰网
Engineering at Meta
Engineering at Meta
WordPress大学
WordPress大学
SecWiki News
SecWiki News
N
News and Events Feed by Topic

音视频开发进阶

音视频教程-第三节 音视频教程-第二节 真的,AI 可能就是新时代的信息差 充值 Cursor 之后,工作有了哪些变化?🤔 个人'蒸馏'大模型能做哪些有意思的事情 DeepSeek 大模型在 Mac 上的部署和运行 音视频教程-第一节 【WebRTC 专栏】-- Android 开发集成 WebRTC 库的几种方式 【WebRTC 专栏】-- 在 Mac M1 等系列芯片编译和开发 WebRTC-Android 库 Meta Llama3 大模型在 Mac 上的部署和运行 iOS VideoToolBox 解码 HEVC Open-GOP 视频的问题排查 Flutter 状态管理之 InheritedWidget 使用和分析 用 ChatGPT 回答技术问题怎么样 ? 音视频开发系统入门大致路线 UE 4.27 添加自定义 ShadingModel 用 UE4 虚幻引擎做个捏脸小功能~~ UE4 材质练习 之 凹凸贴图偏移的使用 UE4 材质练习系列基础 OpenGL上下文创建以及共享机制 007 | 播放器系列专栏-解析 MP4 文件读取信息 006 | 播放器系列专栏-在 Mac 上查看 MP4 格式信息 干货 | 快速抽取缩略图是怎么练成的? 关于直播、WebRTC、FFmpeg 的那些事 005 | 播放器系列专栏-在 Windows 上查看 MP4 格式信息 将音视频中的花屏、绿屏、黑屏问题一网打尽 关于音视频里面的解码帧率和渲染帧率 004 | 播放器系列专栏-认识MP4视频(下) 003 | 播放器系列专栏-认识MP4视频(上) 入门或者转行音视频,应该要怎么做? H264视频文件如何缩放分辨率 002 | 播放器系列专栏-FFmpeg依赖库的配置 001 | 播放器系列专栏-关于播放器项目的一个小实践 Seek策略以及在有B帧情况下的处理 目前流媒体开发工程师工作内容主要是什么? 一个音视频领域专业问答的小圈子 干货收藏 || Vulkan Game Engine 视频教程 音视频春节假期内卷指南(实操) Vulkan 在 FFmpeg 中的支持 Windows 下 FFmpeg 和 LibX264 的编译和配置 Metal 开发 | 使用 C++ 进行接口调用 音视频开发工作经验分享 || 视频版 FFmpeg 调用 MediaCodec 硬解码到 Surface 上 代码吸猫 | 用 OpenGL 图像渲染的养猫计划 百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!! 老生常谈-FFmpeg 的编译问题轻松搞定 FFmpeg 调用 Android MediaCodec 进行硬解码(附源码) 【WebRTC 专栏】--创建相机预览 Unity Shader 光照基础之 Half Lambert 光照模型 Unity Shader 光照基础之Lambert光照模型 Unity Shader 光照基础内容 Unity Shader 显示一张图片纹理 UnityShader 的基本概念 Unity 物体的基本操作 C++ 模板系列小结07-尾置返回类型 C++ 模板系列小结06-可变参数模板特性 C++ 中的多线程的使用和线程池建设 C++ 模板系列小结05-模板类型作为模板参数 C++ 模板系列小结04-类模板中的成员模板 C++ 模板系列小结03-在模板中指定变量类型 C++ 模板系列小结02-非类型模板参数 C++ 模板系列小结01-函数模板和类模板 从零打造渲染引擎系列01-什么是渲染引擎 iOS开发 - 在 Swift 中去调用 C/C++ 代码 2021 技术新番 - 从零打造渲染引擎系列 iOS 音视频开发的一些基础准备工作 音视频交流群又来啦~~~ 【WebRTC 专栏】WebRTC & Android 开发学习环境搭建~ 【喜大普奔】域名终于备案通过啦 Shader 优化 | OpenGL 绘制网格效果 【音视频连载-011】第二季 FFmpeg 一层一层获取文件信息 KodeLife | Shader 实时编辑预览的强大工具使用实践 推荐几个堪称教科书级别的 Android 音视频入门项目 【音视频连载-010】第二季 FFmpeg 日志打印 【音视频连载-008】基础学习篇-SDL 播放 PCM 音频文件(下) 【音视频连载-007】基础学习篇-SDL 播放 PCM 音频文件(上) 【音视频连载-006】基础学习篇-SDL 播放 YUV 视频文件 【音视频连载-005】基础学习篇-SDL 加载 YUV 文件并显示 【音视频连载-004】基础学习篇-SDL 加载图片并显示 【音视频连载-003】基础学习篇-SDL 消息循环和事件响应 【音视频连载-002】基础学习篇-SDL 创建窗口并显示颜色 【音视频连载-001】基础学习篇- SDL 介绍以及工程配置 LearnOpenGL 源码在 MAC 上的编译与调试 2019 年终总结与回顾 Android NDK 开发的免费技术视频来啦~~ OpenGL 实现视频编辑中的转场效果 OpenGL 实践之贝塞尔曲线绘制 图像库 libjpeg-turbo 编译与实践 图像库 libpng 编译与实践 Android NDK 开发 —— 从 Assets 文件夹加载图片并上传纹理 简单易用的图像解码库介绍 —— stb_image 博客图床迁移记 进击的 Vulkan 移动开发之 SwapChain 进击的 Vulkan 移动开发之 Command Buffer 进击的 Vulkan 移动开发之 Instance & Device & Queue 进击的 Vulkan 移动开发(一)之今生前世 Java 显式锁 Lock 与条件队列 C++ 标准容器库小结 MediaCodec 硬编码之相机内容编码成 H264 文件 一文读懂 YUV 的采样与格式 《OpenGL ES 3.x 游戏开发》碰撞检测之 AABB 包围盒
rust 开发编译 Android 动态库实践
音视频开发进阶 · 2019-05-19 · via 音视频开发进阶

一个专注音视频领域的小圈子

最近关注了一波 rust,一门目前还比较小众但却很强大的编程语言,官网地址如下:

https://www.rust-lang.org/ rust 的学习曲线比较陡峭,在开始学习之前建议看看王垠的这篇文章 《如何掌握所有的编程语言》,地址如下: https://www.yinwang.org/blog-cn/2017/07/06/master-pl 学习语言,重要的是掌握其语言特性。 王垠举了一些语言特性的例子:

  • 变量定义
  • 算术运算
  • for 循环语句,while 循环语句
  • 函数定义,函数调用
  • 递归
  • 静态类型系统
  • 类型推导
  • lambda 函数
  • 面向对象
  • 垃圾回收
  • 指针算术
  • goto 语句 看着这些特性是不是很像一些编程语言书的目录🤔 在学习 rust 的时候也可以照着这些语言特性去对比自己是否掌握了。 那么 rust 到底强大在哪里?在 Kotlin 刚出的时候宣传的点就是空安全 ,弥补 Java 在这方面的不足。而 rust 可以说对比的是 C++,弥补 C++ 在空指针和野指针(悬垂指针)方面的不足,当然 rust 的优势还不足如此。

以下是来自维基百科的介绍,有些特性我暂时还没体验过,先摘录一波:

Rust 是由 Mozilla 主导开发的通用、编译型编程语言。。设计准则为“安全、并发、实用”,支持函数式、并发式、过程式以及面向对象的编程风格。

目前国内也已经有一些团队在用 rust 进行开发了,可以在观望一波后,再决定是否投入精力入坑~~~


rust 编译 so 实践

下面是用 rust 编译 Android 动态库实践,主要参考了 Mozilla 给的例子,具体链接在后面。

安装 rust

首先是安装 rust ,通过如下命令安装:

curl https://sh.rustup.rs -sSf | sh

然后通过如下命令输出 rust 版本以及验证是否安装成功。

配置 rust 交叉编译

确保 Android 的 sdk 目录配置到了系统环境中。

export ANDROID_HOME=/Users/$USER/Library/Android/sdk
export NDK_HOME=$ANDROID_HOME/ndk-bundle

然后执行如下命令:

mkdir NDK
${NDK_HOME}/build/tools/make_standalone_toolchain.py --api 26 --arch arm64 --install-dir NDK/arm64
${NDK_HOME}/build/tools/make_standalone_toolchain.py --api 26 --arch arm --install-dir NDK/arm
${NDK_HOME}/build/tools/make_standalone_toolchain.py --api 26 --arch x86 --install-dir NDK/x86

主要是执行 ndk-bundle 目录下的 python 脚本,该脚本在 NDK 目录中去创建 arm64、arm、x86 架构平台的编译环境。

在把环境添加到 rust 的配置中。

创建 cargo-config.toml 文件,输入如下内容:

[target.aarch64-linux-android]
ar = "<path>/NDK/arm64/bin/aarch64-linux-android-ar"
linker = "<path>/NDK/arm64/bin/aarch64-linux-android-clang"

[target.armv7-linux-androideabi]
ar = "<path>/NDK/arm/bin/arm-linux-androideabi-ar"
linker = "<path>/NDK/arm/bin/arm-linux-androideabi-clang"

[target.i686-linux-android]
ar = "<path>/NDK/x86/bin/i686-linux-android-ar"
linker = "<path>/NDK/x86/bin/i686-linux-android-clang"

记得把 替换成 NDK 文件夹所在的路径。

然后执行:

cp cargo-config.toml ~/.cargo/config

把 cargo-config.toml 移动到 ~/.cargo/ 目录下。

再执行如下命令:

rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android

以上就完成了交叉编译环境的配置。

rust 开发及编译

现在要涉及到具体的 rust 开发了,推荐使用 JetBrains 系列的 IntelliJ IDEA ,无需激活,使用社区版就行,安装 rust 插件就可以愉快地编写代码了。

执行以下命令创建工程目录:

mkdir rust-android
cd rust-android

然后创建 rust 项目:

cargo new rust --lib
cd rust

rust 代表创建的项目所在文件夹名字。

--lib 代表我们创建的是一个库项目,而不是一个执行的二进制文件。

项目结构图如下:

结构很简单,就两个文件,本篇文章也不会自己去新增文件,当然肯定是会有编译文件出现的。

Cargo.toml 就相当于 Android 中的 build.gradle ,一些第三方库都是通过这里去引用的。

lib.rs 就是具体编写代码的地方了。

首先要在 Cargo.toml 中去添加一些内容:

[dependencies]
# 添加 jni 依赖,并指定版本
jni = { version = "0.10.2", default-features = false }

[profile.release]
lto = true

[lib]
# 编译的动态库名字
name = "rust"
# 编译类型 cdylib 指定为动态库
crate-type = ["cdylib"]

关于添加的内容含义如上注释,主要是添加了 jni 依赖和指定编译,有了 jni 依赖才能够让 Android 项目代码调用到 so 动态库的内容。

接下来就是编写 rust 代码了。

// 指定 os 类型
#![cfg(target_os = "android")]
// 允许不是 snake_case 的命令方式
#![allow(non_snake_case)]

// 引用标准库的一些内容
use std::ffi::{CString, CStr};
// 引用 jni 库的一些内容,就是上面添加的 jni 依赖
use jni::JNIEnv;
use jni::objects::{JObject, JString};
use jni::sys::jstring;

#[no_mangle]
// jni 函数调用的头
pub unsafe extern fn Java_com_glumes_rust_MainActivity_hello(
    env: JNIEnv, _: JObject, j_recipient: JString) -> jstring {
    // 将 Android 上层传来的字符串转出 rust 中的字符串变量
    let recipient = CString::from(
        CStr::from_ptr(
            env.get_string(j_recipient).unwrap().as_ptr()
        )
    );
    // 返回一个新的字符串
    let output = env.new_string("hello".to_owned() + recipient.to_str().unwrap()).unwrap();
    output.into_inner()
}

抛开 rust 具体语法不看,代码内容也很简单,传一个字符串,返回一个新的字符串。

接下来就是执行具体的编译:

cargo build --target aarch64-linux-android --release
cargo build --target armv7-linux-androideabi --release
cargo build --target i686-linux-android --release

分别执行上面三个命令,会分别构建三个不同平台的 so 库。

然后把 so 库替换到 Android 项目的 jniLibs 具体文件夹就好了。

这样就完成了用 rust 编译 Android 平台的 so 动态库,并且每次编译后的时候就要进行 so 的替换,当然也可以想办法把 rust so 的编译放在 Android gradle 的编译过程中,就和用 CMake 编译一样。

问题和思考

以上只是一个小小的例子,想用 rust 实现像 C++ 那样去开发动态库,可能还一些坑要去探索。仅仅是实现 jni 的调用还是远不够的,在 NDK 开发里面还有很多头文件,如何去在 rust 里面去实现调用?

如果想要 rust 去打印 Android NDK 中的 log ,倒是可以参考 android_logger-rs 项目,至于其他的慢慢摸索中。

另外还有个问题,如何在 Android 中去断点调试 rust 的代码,在网上搜索了一番,还没找到合适的答案,有知道的朋友可以指点我一二 🥺

参考

具体的例子可以参考我的 GitHub 项目:

https://github.com/glumes/rust-android-example

  1. https://www.yinwang.org/blog-cn/2017/07/06/master-pl
  2. https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-21-rust-on-android.html

原创文章,转载请注明来源:    rust 开发编译 Android 动态库实践