• 正文
  • 相关推荐
申请入驻 产业图谱

一个面向嵌入式Linux C++的应用开发框架!

10/30 13:19
382
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

一、项目简介

AppKit是一个专注于嵌入式Linux应用开发的C++14框架,它的核心目标是提升开发效率和应用健壮性。AppKit提供了一套经过验证的工具集,覆盖了线程管理、定时器、文件IO、串口通信、网络通信、CAN总线GPIO控制等嵌入式开发中的高频需求。

https://gitee.com/newgolo/appkit

双环境支持: 同时支持ROS和非ROS环境编译,既能用于机器人项目,也能用于传统嵌入式应用

跨平台构建: 内置zbuild编译系统,支持x86_64和aarch64平台的本地编译与交叉编译

工程化实践

集成了fmt、spdlog、json、yaml-cpp等成熟的第三方库,避免重复造轮子

二、整体架构

2.1 顶层架构

AppKit的设计哲学是"分层解耦,按需组合"。整个项目分为三个核心层次:

解耦合:核心库不依赖第三方库的具体实现,通过接口隔离

可扩展:新增功能模块只需遵循统一的构建规范,无需修改框架核心

2.2 目录结构解析

项目采用了标准化的ROS工作空间布局,即使在非ROS环境下也保持了这种结构:

appkit/
├── environ/ ? ? ? ? ? ? ?# 环境配置中枢
│ ? ├── cmake/ ? ? ? ? ??# CMake工具集
│ ? │ ? ├── zbuild.cmake ? ? ?# zbuild函数定义
│ ? │ ? ├── finder.cmake ? ? ?# 依赖查找
│ ? │ ? └── common.cmake ? ? ?# 通用配置
│ ? ├── config/ ? ? ? ? ?# 平台配置文件
│ ? │ ? ├── linux-amd64.sh ? ?# x64配置
│ ? │ ? └── linux-arm64.sh ? ?# ARM64配置
│ ? ├── zbuild/ ? ? ? ? ?# zbuild工具脚本
│ ? └── envsetup.sh ? ? ?# 环境初始化脚本
├── src/
│ ? ├── appkit/ ? ? ? ? ?# 核心库源码
│ ? │ ? ├── inc/ ? ? ? ??# 公共头文件
│ ? │ ? └── src/ ? ? ? ??# 实现代码
│ ? ├── third_party/ ? ??# 第三方依赖
│ ? ├── demos/ ? ? ? ? ??# 示例程序
│ ? └── include/ ? ? ? ??# 全局公共头文件
├── prebuilt/ ? ? ? ? ? ?# 预编译库存放
│ ? ├── linux-amd64/
│ ? └── linux-arm64/
├── zbuild/ ? ? ? ? ? ? ?# 非ROS编译入口
└── ws_output/ ? ? ? ? ??# ROS编译输出

关键设计点

environ目录:这是整个构建系统的大脑。envsetup.sh通过source的方式注入环境变量,让用户在shell中就能调用zbuild_setup等函数。这种设计比传统的Makefile更灵活,可以根据平台动态配置。

setup.cmake:每个package的CMakeLists.txt都会include这个文件。它统一管理了编译选项、依赖路径、宏定义等,避免了各模块的配置不一致。

prebuilt机制:交叉编译时,先将库安装到prebuilt目录,其他模块再从这里链接。这避免了交叉编译环境下的路径混乱问题。

2.3 构建系统设计

AppKit支持三种编译模式:

zbuild的核心机制

通过环境变量ZBUILD_ENABLE来区分编译模式。当ZBUILD_ENABLE=1时,所有package的CMakeLists.txt都会走非ROS的编译分支:

这种设计的精妙之处在于:同一份CMakeLists.txt,通过环境变量控制就能适配两种完全不同的构建系统。避免了维护两套构建脚本的麻烦。

三、部分代码

3.1 线程封装:Runnable模式

AppKit的线程设计采用了经典的Runnable模式:

使用示例

设计优势:线程逻辑与线程对象分离,符合单一职责原则run()函数可以访问Thread对象,方便检查退出标志支持线程克隆,适合需要动态创建多个相同类型线程的场景

3.2 定时器管理:统一调度

嵌入式系统中常常需要管理大量定时器,如果每个定时器都开一个线程,资源消耗很大。AppKit采用了单线程集中调度的方式:

关键点

    所有定时器共享一个线程,每1ms检查一次定时器回调在TimerManager的线程中执行,注意不要阻塞适合周期在100ms以上的定时任务,对于高精度定时建议使用硬件定时器

3.3 应用框架:Component模式

AppKit提供了一个轻量级的应用框架,类似于ROS的节点概念:

这种设计让应用的生命周期管理变得清晰:

优势

    统一的生命周期管理,不会遗漏资源释放任务自动在后台线程池中执行,无需手动管理线程支持多组件组合,构建复杂应用

四、实战示例

4.1 定时器

#include?<appkit/async.h>
#include?<appkit/console.h>
#include?<appkit/datetime.h>
#include?<appkit/strutil.h>
#include?<appkit/timer.h>
#include?<appkit/tracer.h>

usingnamespace?appkit;

void?test_timer_manager()?{
? ??Timer?t1(500,?true);
? ??Timer?t2(1000,?true);
? ? TimerManager tm;
? ? tm.registerTimer(t1, []() { TRACE_INFO("500 ms timer timeout!"); });
? ? tm.registerTimer(t2, []() { TRACE_INFO("1000 ms timer timeout!"); });

? ??while?(1) {
? ? ? ? TRACE_YELLOW("01. start.");
? ? ? ? TRACE_YELLOW("02. stop.");
? ? ? ? TRACE_YELLOW("input q to quit!");
? ? ? ? ConsoleIn ci;
? ? ? ? ci.waitInput();
? ? ? ??if?(ci.asString() ==?"01") {
? ? ? ? ? ? tm.start();
? ? ? ? }?elseif?(ci.asString() ==?"02") {
? ? ? ? ? ? tm.stop();
? ? ? ? }?elseif?(ci.asString() ==?"q"?|| ci.asString() ==?"quit") {
? ? ? ? ? ??break;
? ? ? ? }
? ? }
? ? tm.stop();
}

void?test_timer()?{
? ??while?(1) {
? ? ? ? TRACE_YELLOW("----------timer test--------------");
? ? ? ? TRACE_YELLOW("01. timer manager test.");
? ? ? ? TRACE_YELLOW(" q. quit");
? ? ? ? TRACE_YELLOW("please input selection:");
? ? ? ? ConsoleIn ci;
? ? ? ? ci.waitInput();
? ? ? ??if?(ci.asString() ==?"01") {
? ? ? ? ? ? test_timer_manager();
? ? ? ? }?elseif?(ci.asString() ==?"02") {
? ? ? ? ? ??//
? ? ? ? }?elseif?(ci.asString() ==?"q"?|| ci.asString() ==?"quit") {
? ? ? ? ? ??break;
? ? ? ? }
? ? }
}

五、总结

5.1 值得学习的地方

Runnable模式的线程封装:比直接使用std::thread更符合OOP思想,线程逻辑可复用、可测试

Component生命周期管理:四阶段(init/start/stop/deinit)让资源管理不再混乱

TimerManager的单线程调度:以较小的代价支持多定时器,适合资源受限的嵌入式系统

环境变量驱动的构建系统:灵活性高于硬编码的Makefile,易于扩展

 

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

本公众号专注于嵌入式技术,包括但不限于C/C++、嵌入式、物联网、Linux等编程学习笔记,同时,公众号内包含大量的学习资源。欢迎关注,一同交流学习,共同进步!