Linux上位机开发实战(编写API库)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
我们自己编写linux上位机软件的时候,尽量都是通过框架+库的形式来开发。这就是所谓的低耦合,高内聚。相似的功能、模块和算法,都可以做成一个静态库,或者是动态库。实际操作中,客户一般喜欢设计为动态库。因为相比较动态库而言,静态库需要重新编译,比较麻烦。而动态库,即使有bug,直接替换dll、so文件即可。

1、API库的构成
提供给客户的API库,从技术上说一般包含了head头文件、so动态库文件即可。另外,从版权保护的角度来说,通常还包含一个license文件,或者是一个usb key。
2、编程语言
通常来讲,接口都会是c语言开发的,实现部分可以是c,也可以是c++。这样,即使客户是用其他语言开发的,也只需要把库文件简单做一个语言封装,这样就可以比较容易地转到其他编程语言,比如说c#、java、python、js、ruby、perl、go等等。
3、基本原则
对外输出的动态库,最重要的原则,就是只提供必要的信息,隐藏实现的细节。对外提供的函数,一般都是包括在header头文件里面。中间如果涉及到复杂的结构体,最好也是用void*表示。实际开发库的时候,我们自己习惯用cpp开发,但是发布给客户,一定要用extern "C"包装一下。
4、文档部分
除了技术的部分,详细的使用文档也是必不可少的。每一个api是什么意思,对应的参数是什么,都需要详细地告诉用户。用户可能也不一定看,但是交付的时候,还是有必要提供的。和代码版本一样,文档部分,我们也要做好版本管理。
5、demo代码
前面说过,客户拿到API库之后,未必会认真查看文档。这种情况下,把范例做好,就可以极大地降低我们开发的工作量。另外,客户的行业、开发水平、人员构成也是千差万别,所以example需要尽量简单,api的命名也尽量简单一些。功能最好直接一点,比如生成的二维码、条形码、人脸识别的位置和概率、车牌识别位置和内容,这种是最合适的。
6、举例说明
假设我们需要写一个图像处理的库。这个时候就需要把实现和接口分开。这里说的分开,并不是说头文件和cpp文件分开,而是说api接口,和类实现分开。
假设实现是这样的,
// header file
#ifndef IMG_PROGRAME_FRAME_H
#define IMG_PROGRAME_FRAME_Hclass ImgProgrameFrame
{
public:ImgProgrameFrame();~ImgProgrameFrame();bool Initialize(bool isRGB, int width, int height);int GetWidth();int GetHeight();bool GetResult(void* p_img, void* p_result);private:void InnerProcess(); // other function defined here};
#endif// cpp file
ImgProgrameFrame::ImgProgrameFrame() {}
ImgProgrameFrame::~ImgProgrameFrame() {}
bool ImgProgrameFrame::Initialize(bool, int, int) { return false; }
int ImgProgrameFrame::GetWidth() { return 0; }
int ImgProgrameFrame::GetHeight() { return 0; }
bool ImgProgrameFrame::GetResult(void*, void*) { return true; }
void ImgProgrameFrame::InnerProcess() {}; // other function implementation
但是给客户的API接口肯定不是这样,上面的实现只能我们自己看到。不可能把class的细节都给客户,
// header file
#ifndef IMG_PROGRAME_FRAME_API_H
#define IMG_PROGRAME_FRAME_API_Hvoid Initialize(bool isRGB, int width, int height);
int GetWidth();
int GetHeight();
bool GetResult(void* img,void* param);
#endif// cpp file
static class ImgProgrameFrame _gFrame;
void Initialize(bool isRGB, int width, int height)
{_gFrame.Initialize(isRGB, width, height);
}int GetWidth() { return _gFrame.GetWidth(); }
int GetHight() { return _gFrame.GetHeight(); }
bool GetResult(void* img, void* result) { return _gFrame.GetResult(img, result); }
和具体的实现相比较,对外提供的接口都比较简洁。类中的变量、私有函数、部分public函数都会做一个提取之后,再转交给客户。或者说,我们提供给客户的部分,只是客户愿意付费的那部分。这是比较方便、也比较合理的一个做法。
当然如果需要并发处理,一般就会生成一个动态的ImgProgrameFrame对象,通过void*给客户,每次客户使用的时候再传进来即可。类似于这样,
// header file
#ifndef IMG_PROGRAME_FRAME_API_H
#define IMG_PROGRAME_FRAME_API_Hvoid* InitializeObject(bool isRGB, int width, int height);
int GetWidth(void* p);
int GetHeight(void* p);
bool GetResult(void*p, void* img, void* result);
#endif// cpp file
void* InitializeObject(bool isRGB, int width, int height)
{ImgProgrameFrame* p = new ImgProgrameFrame();p->Initialize(isRGB, width, height);return (void*)p;
}int GetWidth(void* p)
{return ((ImgProgrameFrame*)(p))->GetWidth();
}int GetHeight(void* p)
{return ((ImgProgrameFrame*)(p))->GetHeight();
}bool GetResult(void*p, void* img, void* result)
{return ((ImgProgrameFrame*)(p))->GetResult(img, result);
}
相关文章:
Linux上位机开发实战(编写API库)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 我们自己编写linux上位机软件的时候,尽量都是通过框架库的形式来开发。这就是所谓的低耦合,高内聚。相似的功能、模块和算法…...
深入浅出JVM性能优化:从理论到实践
一、JVM架构与内存模型深度解析 1.1 JVM运行时数据区全景图 方法区(元空间):存储类信息、常量池等元数据堆内存:对象实例存储核心区域 Young Generation(新生代) Eden区(对象诞生地࿰…...
Redis Sentinel 详解
Redis Sentinel 详解 1. 什么是 Redis Sentinel?有什么用? Redis Sentinel(哨兵) 是 Redis 官方提供的高可用性解决方案,主要用于监控、通知和自动故障转移。当 Redis 主节点(master)发生故障…...
器件功耗模型原理
器件功耗模型原理 谷歌提供了一套通用的器件耗电模型和配置方案,先对器件进行耗电因子拆解,建立器件功耗模型,得到一个器件耗电的计算公式。通过运行时统计器件的使用数据,代入功耗模型,就可以计算出器件的功耗。例如…...
拥抱成长型思维:解锁持续进步的人生密码
我强烈推荐4本可以改变命运的经典著作: 《寿康宝鉴》在线阅读白话文《欲海回狂》在线阅读白话文《阴律无情》在线阅读白话文《了凡四训》在线阅读白话文 一、什么是成长型思维? 成长型思维(Growth Mindset)由斯坦福大学心理学家卡…...
Ubuntu上查看GPU使用情况并释放内存
先用nvidia-smi查看GPU当前使用情况 再用fuser 命令查找对应显卡上占用 GPU 的进程 最后查到了用kill -9强制杀掉进程(PID)即可...
解决思科交换机无法访问局域网外设备
问题背景 有时,我们需要远程连接来管理一台思科交换机,例如使用SSH协议。然而交换机运作在链路层,这就需要交换机有一个网络层地址,来接纳基于IP协议的远程访问请求。于是,我们依靠设置一个带有IP地址的交换机虚拟接口…...
Unity Shader编程】之透明物体渲染
以下是针对您提出的关于 Unity Shader 渲染 Pass 的查看方法、多个 Pass 的影响、Pass 的含义,以及 Unity 渲染物体的流程和处理多个透明/半透明/不透明物体的详细解答。 1. Unity Shader 渲染 Pass 的查看方法 查看 Pass 的方法 通过 Shader 代码: 打开…...
fopen和open 等区别是什么?文件描述符与文件描述指针区别
FILE *fp fopen(path, "w"); int fd open(path,) 1.区别 函数定义所属库返回类型fopen高级文件操作函数,提供缓冲机制标准 C 库 (stdio.h)FILE*(文件指针)open低级文件操作函数,直接调用系统接口Unix/Linux 系统调用…...
什么是张量计算
以下是对张量计算的详细介绍,结合数学、物理学及计算机科学等多领域视角: 一、张量的基本定义与性质 1. 张量的数学定义 张量是向量空间及其对偶空间的笛卡尔积上的多重线性映射,可视为多维数组或几何对象。其核心特征在于: 坐…...
【1】Java 零基础入门学习(小白专用)
【1】Java 零基础入门学习 📚博客主页:代码探秘者 ✨专栏:《JavaSe从入门到精通》 其他更新ing… ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏作者水…...
[c语言日寄]枚举类型
【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…...
替代-UX设计师
初创公司如何在没有设计师的情况下 打造实用的用户体验 一个常见的捷径是使用预构建的组件库,如谷歌的 Material UI它们为你提供了构建块,但它们并没有为你考虑整个用户流程你仍然需要弄清楚所有这些是如何组合在一起的但是,很多时候&#x…...
【氧化镓】掺杂在β-Ga2O3材料中引入的深能级缺陷
1. 引言 1.1 β-Ga2O3材料的特性与应用前景 β-Ga2O3作为一种新型的宽禁带半导体材料,具有约4.6-4.8 eV的宽带隙、高击穿场强(约8 MV/cm)和优异的热稳定性,适用于高功率和射频电子器件。其独特的物理特性使其在高电压、高频率以及高功率应用场景中具有巨大的潜力。例如,…...
:ref 和 this.$refs 的区别及 $ 的作用
:ref 在 Vue 模板中,:ref 这种写法是使用了 Vue 的动态绑定语法(: 是 v-bind: 的缩写)。ref 是一个特殊的属性,用于给元素或组件注册引用信息。当你使用 :ref 时,通常是在动态地为元素或组件设置引用名称,…...
分库分表后,跨库查询和分布式事务解决方案
分库分表主要是为了解决单库单表的性能瓶颈,但拆分后数据分散在不同库和表中,这就导致了跨库查询和分布式事务的问题。 以下是实际项目中应对这些问题的核心策略与技术实现: 一、跨库查询解决方案 1. 全局表(广播表) 适用场景:基础数据表(如地区表、配置表)数据量小且…...
仅靠prompt,Agent难以自救
Alexander的观点很明确:未来 AI 智能体的发展方向还得是模型本身,而不是工作流(Work Flow)。还拿目前很火的 Manus 作为案例:他认为像 Manus 这样基于「预先编排好的提示词与工具路径」构成的工作流智能体,…...
android初学
Intent直译意图 显式意图:构造函数(实参为两个) (当前类对象 this,要跳转的.javaclass文件), 隐式意图:构造方法实参(填写一个)(需要在清单文件配置)系统自动匹配 点击事件: 注册设置点击监听器的常用三…...
IDEA修改默认作者名称
User: IDEA提示注释缺少author信息,但自动设置后,名称不是我想要的默认名称,应该如何修改IDEA里默认的作者名称? Kimi: 以下是几种修改IntelliJ IDEA中默认作者名称的方法: ### 方法一:修改File and Code …...
Playwright + MCP:用AI对话重新定义浏览器自动化,效率提升300%!
一、引言:自动化测试的“瓶颈”与MCP的革新 传统自动化测试依赖开发者手动编写脚本,不仅耗时且容易因页面动态变化失效。例如,一个简单的登录流程可能需要开发者手动定位元素、处理等待逻辑,甚至反复调试超时问题。而MCP…...
lodash 学习笔记/使用心得
lodash 学习笔记/使用心得 简单记一下 lodash 的一点学习笔记使用心得,最近也是打算清理一下所有的 dead code,然后发现我们用了好多的 lodash 方法。对比了之前的写法,重新看了一下官方文档,再自己重新动手写了点 util 之后发现…...
计算机操作系统(五) 前趋图和程序执行与进程的描述(附带图谱表格更好对比理解))
计算机操作系统(五) 前趋图和程序执行与进程的描述 前言一、前趋图和程序执行1.1前趋图1.2程序的顺序执行1.3程序的并发执行 二、进程的描述2.1进程的定义与特征2.2进程的基本状态与转换2.3挂起的操作系统和进程的转换2.4进程管理中的数据结构 总结&…...
“统计视角看世界”专栏阅读引导
根据文章主题和逻辑关系,我为您设计以下阅读引导方案: #mermaid-svg-xOnE2zTW20jz5myv {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-xOnE2zTW20jz5myv .error-icon{fill:#552222;}#mermaid…...
C/C++静态库的理解和制作
1.什么是库 库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。 本质上来说库是⼀种可执行代码的二进制形式,可以被操作系统…...
【redis】主从复制:单点问题、配置详解、特点详解
文章目录 单点问题什么是主从复制主从模式能解决的问题并发量有限可用性问题 配置建立复制通过配置文件来指定端口配置主从查看集群结构 断开复制 特点安全性只读传输延迟 单点问题 分布式系统中,涉及到一个非常关键的问题:单点问题 某个服务器程序&…...
OpenCV HighGUI 模块使用指南(Python 版)
用户让我编写一个 HighGUI 模块的使用指南,包括函数的使用和应用场景的实现。首先,我需要回顾 HighGUI 模块的主要功能:图像显示、视频捕获、鼠标和键盘事件。然后,按照用户提供的结构,整理每个部分的函数详解、代码示…...
PyTorch 面试题及参考答案(精选100道)
PyTorch 的动态计算图与 TensorFlow 的静态计算图有何区别?动态图的优势是什么? PyTorch 的动态计算图和 TensorFlow 的静态计算图在构建方式、灵活性和调试难度等方面存在显著区别。 在构建方式上,TensorFlow 的静态计算图需要先定义好整个…...
android......
事件源,就是视图对象,先注册一个监听器,等待用户触发了屏幕,一旦触发会立即产生一个事件源,事件源会生成一个用户点击的触发事件,此刻监听器会立马监听到 ,然后监听器调用回调方法 UI理解 全称用…...
常见中间件漏洞(tomcat)
CVE-2017-12615 当在Tomcat的conf(配置目录下)/web.xml配置文件中添加readonly设置为false时,将导致该漏洞产生,(需要允许put请求) , 攻击者可以利用PUT方法通过精心构造的数据包向存在漏洞的服务器里面上传…...
计算机网络高频(二)TCP/IP基础
计算机网络高频(二)TCP/IP基础 1.什么是TCP/IP⭐⭐ TCP/IP是一种网络通信协议,它是互联网中最常用的协议之一。TCP/IP有两个基本的协议:TCP(传输控制协议)和IP(互联网协议)。 TCP(Transmission Control Protocol,传输控制协议)是一种可靠的、面向连接的协议。它负…...
