(三) 搞定SOME/IP通信之CommonAPI库
本章主要介绍在SOME/IP通信过程中的另外一个IPC通信利剑,CommonAPI库,文章将从如下几个角度让读者了解什么是CommonAPI, 以及库在实际工作中的作用
文中资源:vsomeip+commonapi+指导文档与demo源码
SOME/IP通信之CommonAPI
- CommonAPI库是什么
- CommonAPI库的编译
- 写个Demo实战一下
CommonAPI库是什么
CommonAPI是GENIVI组织开发的一个基于C++的应用API库,没错,跟vsomeip协议栈是一个爹。其主要提供给使用通讯中间件传输数据的分布式应用来操作通讯中间件的接口。主要的作用是使使用CommonAPI进行IPC通信的的应用能够隔离底层协议栈的差异。比如使用CommonAPI时,我们的底层协议栈可以是vsomeip,也可以是DBUS等. 他的架构如下:

从图中可以看到,CommonAPI C++ 框架分为两个主要部分:
CommonAPI Core: 这部分与中间件无关,包含了跨不同中间件技术共享的基本 API、类和组件。它提供了构建应用程序所需的基本通信机制和抽象,而不与特定的中间件协议绑定。
CommonAPI Binding: 这部分与特定中间件相关,并包含了每种支持的中间件协议的实现细节。
通过将Core与Binding分开,CommonAPI C++ 允许开发人员使用与中间件无关的核心编写他们的应用程序逻辑,使其代码更具可移植性,不会紧密绑定到特定的中间件。然后,他们可以选择特定的绑定,将他们的应用程序适配到所需的中间件技术,而无需重写整个应用程序逻辑。
这种关注点分离使得开发更容易,可以在具有不同中间件要求的各种汽车系统中部署应用程序。它通过在中间件无关逻辑和特定中间件实现细节之间提供明确的分离,促进了可重用性和模块化。
图右边的四个框架,分别代表了Core层的代码生成工具,以及接口描述语言(fidl), Binding层的代码生成工具,以及接口描述语言(fdepl),即:
Code Generator Tools <--> *.fidl
Code Generator Binding Tools <--> *.fdepl
关于fidl跟fdepl文件是什么,如果你做过android开发,那么对aidl文件以及hidl文件会比较熟悉,这个fidl跟fdepl文件也是跟aidl&hidl的作用类似,我们将通信行为的接口以及参数定义在文件中,通过CommonAPI提供的Code Generators,即可将这些文件转成对应的C++接口。上层在在进行IPC接口时,只需要调用这些C++中的接口即可
CommonAPI库的编译
因为我们是基于android系统来使用CommonAPI通信,故使用ndk+gradle来编译库
编译环境
操作系统:win11
Gradle: 7.3.3
cmake版本:3.18.1
下载源码
这里包含两部分,一个是CommonAPI Core,一个是CommonAPI Binding分别对应如下两个库:
capicxx-core-runtime
capicxx-someip-runtime
下载完成后,将文件夹拷贝到上一篇文章提供的附件工程中的external目录下面,放好后如下所示:

修改CMakeList
然后我们需要修改工程根目录下的CMakeLists.txt文件, 注意是工程根目录,不是模块根目录,修改后内容如下所示:
cmake_minimum_required(VERSION 3.10)project(SOMEIP)list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/output/${ANDROID_ABI})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/output/${ANDROID_ABI})
set(FETCHCONTENT_SOURCE_DIR_BOOST ${CMAKE_CURRENT_SOURCE_DIR}/external/boost_1_71_0)
add_subdirectory(external/boost-cmake)
add_subdirectory(external/vsomeip)
add_subdirectory(external/capicxx-core-runtime-master)
add_subdirectory(external/capicxx-someip-runtime-master)
add_subdirectory(app/src/main/cpp)
external/capicxx-core-runtime-master/CMakeLists.txt
#添加编译标记,不然会编译报错(-Wno-ignored-attributes -Wno-deprecated-declarations)
IF(MSVC)message("using MSVC Compiler")add_definitions(-DCOMMONAPI_INTERNAL_COMPILATION -DCOMMONAPI_DLL_COMPILATION)add_compile_options(/EHsc /wd4996)
ELSE ()set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector -fasynchronous-unwind-tables -fno-omit-frame-pointer -Werror -DCOMMONAPI_INTERNAL_COMPILATION -fvisibility=hidden -Wno-ignored-attributes -Wno-deprecated-declarations")
ENDIF(MSVC)
external/capicxx-core-runtime-master/CMakeLists.txt
if ("${USE_INSTALLED_COMMONAPI}" STREQUAL "ON")FIND_PACKAGE(CommonAPI 3.2.0 REQUIRED CONFIG NO_CMAKE_PACKAGE_REGISTRY)
else()
# 注释掉REQUIRED
# FIND_PACKAGE(CommonAPI 3.2.0 REQUIRED CONFIG NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH)FIND_PACKAGE(CommonAPI 3.2.0)
endif()# maintainer-clean target去掉
if(NOT ANDROID)
add_custom_target(maintainer-clean COMMAND rm -rf *)
endif()
在根目录的cmake文件夹下再按照cmake的find_package规则添加两个文件,FindCommonAPI.cmake, 跟FindCommonAPI-SomeIP.cmake 两个文件
然后启动编译,就可以在工程根目录的output目录下看到库基本已经全部输出了

写个Demo实战一下
上面库编译完成了,书接上回的vsomeip demo,我们需要将someip_server跟someip_client这两个库改造以下,不直接使用vsomeip协议栈的API, 改为CommonAPI的方式来实现。
在写代码之前,咱们来回顾一下之前使用vsomeip协议栈API写的例子,我们定义了一个天气服务,然后服务中提供了一个获取温度的方法,参数如下:
//服务ID
static vsomeip::service_t weather_service_id = 0x1001;
//服务实例ID
static vsomeip::instance_t weather_service_instance_id = 0x0001;
//方法ID
static vsomeip::method_t weather_get_temp_method_id = 0x0001;
这里我们把它改造成CommonAPI的方式,首先在cpp目录下创建如下两个文件,并填入内容:
IWeatherService.fidl
package com.commapi.testinterface IWeatherService {version { major 0 minor 1 }method getTemp {out {Int32 temp}}
}
IWeatherService.fdepl
import "platform:/plugin/org.genivi.commonapi.someip/deployment/CommonAPI-4-SOMEIP_deployment_spec.fdepl"
import "IWeatherService.fidl"define org.genivi.commonapi.someip.deployment for interface com.commapi.test.IWeatherService {SomeIpServiceID = 4097 //0x1001method getTemp {SomeIpMethodID = 1 //0x0001SomeIpReliable = true}
}define org.genivi.commonapi.someip.deployment for provider as Service {instance com.commapi.test.IWeatherService {InstanceId = "com.commapi.test.IWeatherService"SomeIpInstanceID = 1 //0x0001}
}
我们这里只展示使用方式,fidl&fdepl的语法,我们后面会专门起文章来介绍。
写好后,需要下载如下两个工具:
commonapi_core_generator-3.2.0
commonapi_someip_generator-3.2.0.1
下载完成后,解压到执行的目录, 然后启动cmd窗口,跳转到我们的fidl & fdepl文件所在目录,然后输入如下命令,即可:
commonapi-core-generator-windows-x86_64.exe -sk *.fidl
commonapi-someip-generator-windows-x86_64.exe *.fdepl

这里我们会发现我们的fidl文件夹下多了自动生成了一个src-gen的文件夹,内容如下:

接下来改造server端跟client端,第一步先把cpp跟.h文件加入到编译源文件中, 修改cpp目录下的CMakeLists.txt如下:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html# Sets the minimum version of CMake required to build the native library.cmake_minimum_required(VERSION 3.18.1)# Declares and names the project.
project("someip")find_package (vsomeip3 3.3.8 REQUIRED)
find_library(log-lib log)
include_directories(${VSOMEIP3_INCLUDE_DIRS})# CommonAPI
find_package(CommonAPI 3.2.0 REQUIRED)
include_directories(${COMMONAPI_INCLUDE_DIRS})# CommonAPI-SomeIP
find_package(CommonAPI-SomeIP 3.2.0 REQUIRED)
include_directories(${CommonAPI-SomeIP_INCLUDE_DIRS})# SRC-GEN
include_directories(fidl/src-gen)
file(GLOB SRC-GEN fidl/src-gen/v0/com/commapi/test/*.cpp)add_executable(someip_server# Provides a relative path to your source file(s).someip_server.cpp${SRC-GEN})target_link_libraries(someip_server ${log-lib} vsomeip3 vsomeip3-e2e vsomeip3-sd CommonAPI CommonAPI-SomeIP)add_executable(someip_client# Provides a relative path to your source file(s).someip_client.cpp${SRC-GEN})target_link_libraries(someip_client ${log-lib} vsomeip3 vsomeip3-e2e vsomeip3-sd CommonAPI CommonAPI-SomeIP)
编译文件修改完成后,再将我们之前的vsomeip的两个端代码修改为CommonAPI方式,对应两个文件如下:
服务端实现:someip_server.cpp
#include <string>
#include <csignal>
#include <unistd.h>
#include "CommonAPI/CommonAPI.hpp"
#include "v0/com/commapi/test/IWeatherServiceStubDefault.hpp"using namespace v0::com::commapi::test;class WeatherServiceStub : public IWeatherServiceStubDefault {
private:int temp = -32;
public:WeatherServiceStub() = default;~WeatherServiceStub() override = default;void getTemp(const std::shared_ptr<CommonAPI::ClientId> _client, getTempReply_t _reply) override{printf("%s : gid[%d], uid[%d]\n", __func__ , _client->getGid(), _client->getUid());_reply(temp++);}
};int main(int args, char** argc){//设置配置文件路径setenv("COMMONAPI_CONFIG", "vendor/etc/commonapi.ini",1);setenv("VSOMEIP_CONFIGURATION", "/vendor/etc/local_server.json", 1);auto runtime = CommonAPI::Runtime::get();auto weather_service = std::make_shared<WeatherServiceStub>();auto server_register = runtime->registerService("local","com.commapi.test.IWeatherService",weather_service,"someip_server");printf("register weather service : %d\n", server_register);while(true){usleep(1000 * 1000);}return 1;
}
客户端实现:someip_client.cpp
#include <string>
#include <csignal>
#include <unistd.h>
#include "thread"
#include "CommonAPI/CommonAPI.hpp"
#include "v0/com/commapi/test/IWeatherService.hpp"
#include "v0/com/commapi/test/IWeatherServiceProxy.hpp"using namespace v0::com::commapi::test;int main(int args, char** argc){setenv("COMMONAPI_CONFIG", "vendor/etc/commonapi.ini",1);setenv("VSOMEIP_CONFIGURATION", "/vendor/etc/local_client.json", 1);auto runtime = CommonAPI::Runtime::get();auto app = runtime->buildProxy<IWeatherServiceProxy>("local","com.commapi.test.IWeatherService","someip_client");while(true){if(!app->isAvailable()){printf("connecting failed, retry\n");sleep(1);continue;}break;}app->getProxyStatusEvent().subscribe([&app](CommonAPI::AvailabilityStatus status){if(status == CommonAPI::AvailabilityStatus::AVAILABLE){printf("service available\n");std::thread t1([&app]{for(int i=0; i<10; i++){CommonAPI::CallStatus callStatus;int32_t temp;CommonAPI::CallInfo callInfo;app->getTemp(callStatus, temp, &callInfo);printf("CallStatus = %d, getTemp: %d\n",callStatus, temp);}});t1.detach();}});while(true){usleep(1000 * 1000);}return 1;
}
我这里为了方便仅测试单机模式(双机模式一样的,只是配置不一样)
修改服务端配置local_server.json
{"unicast":"127.0.0.1","logging":{"level":"debug","console":"true"},"applications":[{"name":"someip_server","id":"0x1000"}],"services" :[{"service" : "0x1001","instance" : "0x0001","reliable" : { "port" : "30509", "enable-magic-cookies" : "false" }}],"routing":"someip_server","service-discovery" :{"enable" : "true","multicast" : "239.224.224.245","port" : "30490","protocol" : "udp","initial_delay_min" : "10","initial_delay_max" : "100","repetitions_base_delay" : "200","repetitions_max" : "3","ttl" : "3","cyclic_offer_delay" : "2000","request_response_delay" : "1500"}
}
修改客户端配置:local_client.json
{"unicast":"127.0.0.1","netmask" : "255.255.255.0","logging":{"level":"debug","console":"true"},"applications":[{"name":"someip_client","id":"0x1001"}],"clients" :[{"service" : "0x1001","instance" : "0x0001","reliable" : [ "41234" ]}],"service-discovery" :{"enable" : "false"}
}
然后按照上一篇vsomeip的方式,把库跟文件分别push到系统对应的目录,执行后,即可看到通信正常执行了,如下图。

相关文章:
(三) 搞定SOME/IP通信之CommonAPI库
本章主要介绍在SOME/IP通信过程中的另外一个IPC通信利剑,CommonAPI库,文章将从如下几个角度让读者了解什么是CommonAPI, 以及库在实际工作中的作用 文中资源:vsomeipcommonapi指导文档与demo源码 SOME/IP通信之CommonAPI CommonAPI库是什么C…...
windows bat脚本,使用命令行增加/删除防火墙:入站-出站,规则
常常手动设置防火墙的入站或出站规则,比较麻烦,其实可以用命令行搞定。 下面是禁用BCompare.exe连接网络的例子: ECHO OFF&(PUSHD "%~DP0")&(REG QUERY "HKU\S-1-5-19">NUL 2>&1)||(powershell -Comm…...
Stable Diffusion 告别复制关键词,高质量提示词自动生成插件
在使用SD时,我们经常会遇到心中无想法,或不知如何描述心中所想的图像。有时由于提示词的选择不当,生成的图片质量也不尽如人意。为此,我今天为大家推荐一个高质量的提示词自动生成插件——One Button Prompt。 下面是他生成的一些样图。 文章目录 插件安装插件说明主菜单工…...
【学习日记】【FreeRTOS】任务调度时如何考虑任务优先级——任务的自动切换
写在前面 本文开始为 RTOS 加入考虑任务优先级的自动调度算法,代码大部分参考野火。 本文主要是一篇学习笔记,加入了笔者自己对野火代码的梳理和理解。 一、基本思路 首先我们要知道,在 RTOS 中,优先级越高、越需要被先执行的的…...
C语言暑假刷题冲刺篇——day3
目录 一、选择题 二、编程题 🎈个人主页:库库的里昂 🎐CSDN新晋作者 🎉欢迎 👍点赞✍评论⭐收藏✨收录专栏:C语言每日一练✨其他专栏:代码小游戏C语言初阶🤝希望作者的文章能对你有…...
Taro+vue3小程序开启分享他人和分享到朋友圈
import Taro, { useShareAppMessage, useShareTimeline } from tarojs/taro;onMounted(() > {Taro.showShareMenu({withShareTicket: true,menus: [shareAppMessage, shareTimeline]}); }); useShareAppMessage((res) > {console.log(页面转发的回调)return {title: 开票…...
JAVA-Spring中IOC容器是什么?
目录 JAVA-Spring中IOC容器是什么?什么是IOC?什么是IOC容器?IOC和IOC容器的对比Spring框架中的IOC容器是如何工作的?使用XML配置的ApplicationContext使用注解的AnnotationConfigApplicationContext总结 JAVA-Spring中IOC容器是什…...
QT多屏显示程序
多屏显示的原理其实很好理解,就拿横向扩展来说: 计算机把桌面的 宽度扩展成了 w1(屏幕1的宽度) w2(屏幕2的宽度) 。 当一个窗口的起始横坐标 > w1,则 他就被显示在第二个屏幕上了。 多屏虚拟成一个桌面࿰…...
python使用xlwt时,报ValueError: More than 4094 XFs (styles)
在写表格时,遇到如下报错 一、报错原因 xlwt最多只能有4094个样式,超出这个样式数量就报错了。 二、解决办法 (1)去掉样式的要求...
GitHub 打不开解决方案
GitHub 这几年国内普通用户越来越难以访问,github 作为全球最大的开源平台,里面有用的内容很多,不管是对专业用户还是普通用户,无法访问都是很严重的问题。 1.GitHub 加速镜像 kgithub 是一个公益加速项目,仅需在 gi…...
Java网络编程(一)网络基础
概述 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统、网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递 网络分类 局域网(LAN) 局域网是一种在小区域内使用的,由多台计算机组成的网络,覆盖范围…...
matlab使用教程(17)—多项式的定义和运算
1.创建并计算多项式 此示例说明如何在 MATLAB 中将多项式表示为向量以及根据相关点计算多项式。 1.1 表示多项式 MATLAB 将多项式表示为行向量,其中包含按降幂排序的系数。例如,三元素向量 p [p2 p1 p0]; 表示多项式 创建一个向量以表示二次多项式…...
华为认证 | 这门HCIA认证正式发布!
华为认证云服务工程师HCIA-Cloud Service V3.5(中文版)自2023年8月11日起,正式在中国区发布。 01 发布概述 基于“平台生态”战略,围绕“云-管-端”协同的新ICT技术架构,华为公司打造了覆盖ICT领域的认证体系…...
【Docker】Docker安装 MySQL 8.0,简洁版-快速安装使用
今天,使用docker安装mysql数据库进行一个测试,结果网上找了一篇文章,然后。。。。坑死我… 特总结本篇安装教程,主打一个废话不多说! 坑:安装成功,客户端工具连接不上数据库》。。。 正文&…...
CSS自己实现一个步骤条
前言 步骤条是一种用于引导用户按照特定流程完成任务的导航条,在各种分步表单交互场景中广泛应用。例如:在HIS系统-门诊医生站中的接诊场景中,我们就可以使用步骤条来实现。她的执行步骤分别是:门诊病历>遗嘱录入>完成接诊…...
Visual Studio 2019 解决scanf函数报错问题
前言 Visual Studio 2019 解决scanf函数报错问题 博主博客链接:https://blog.csdn.net/m0_74014525 关注博主,后期持续更新系列文章 *****感谢观看,希望对你有所帮助***** 系列文章 第一篇:Visual Studio 2019 详细安装教程&…...
亚马逊无限买家号如何注册?
如果想要拥有大批量的亚马逊买家号,可以使用亚马逊鲲鹏系统进行自动注册操作。在注册之前我们需要先准备好账号所需要的资料; 1、Ip:软件系统支持11个亚马逊站点使用,因此注册哪一个国家的买家号时就需要购买相应国家的ip&#x…...
前端框架学习-ES6新特性(尚硅谷web笔记)
ECMASript是由 Ecma 国际通过 ECMA-262 标准化的脚本程序设计语言。javaScript也是该规范的一种实现。 新特性目录 笔记出处:b站ES6let 关键字const关键字变量的解构赋值模板字符串简化对象写法箭头函数rest参数spread扩展运算符Promise模块化 ES8async 和 await E…...
普陀发布新规服务元宇宙企业 和数软件发展元宇宙场景落地
近日,数智中国AIGC科技周2023全球元宇宙大会上海站活动现场“半马苏河”元宇宙企业科创政策包正式发布。政策包在普陀原有科创政策基础上进行了叠加升级,一共涵盖了十条专项服务元宇宙企业的专项政策,简称普陀“元十条”。 普陀“元十条”从…...
Kotlin差异化分析,let,run,with,apply及also
作用域函数是Kotlin比较重要的一个特性,共分为以下5种:let、run、with、apply 以及 also,这五个函数的工作方式可以说非常相似,但是我们需要了解的是这5种函数的差异,以便在不同的场景更好的利用它。 读完这篇文章您将…...
【黑客必看】2025最新kali Linux安装教程(超详细),看这一篇就够了
【黑客必看】2025最新kali Linux安装教程(超详细),看这一篇就够了 【黑客必看】kali Linux安装教程(超详细),看这一篇就够了! 一、镜像下载 官网镜像链接:https://cdimage.kali.org/…...
终极指南:3个维度解锁Cyber Engine Tweaks,重塑赛博朋克2077游戏体验
终极指南:3个维度解锁Cyber Engine Tweaks,重塑赛博朋克2077游戏体验 【免费下载链接】CyberEngineTweaks Cyberpunk 2077 tweaks, hacks and scripting framework 项目地址: https://gitcode.com/gh_mirrors/cy/CyberEngineTweaks Cyber Engine …...
RAG检索增强生成技术及应用
首先,是什么? RAG是模型生成回答前从指定知识库中精准抓取信息,再结合这些依据去生成内容,回答问题(给一个学霸配备一个随身图书馆,方便随时查阅) 核心就是:知识库(存资料…...
如何用本地AI工具10倍提升视频字幕提取效率:video-subtitle-extractor完全指南
如何用本地AI工具10倍提升视频字幕提取效率:video-subtitle-extractor完全指南 【免费下载链接】video-subtitle-extractor 视频硬字幕提取,生成srt文件。无需申请第三方API,本地实现文本识别。基于深度学习的视频字幕提取框架,包…...
FlowScope:一款注重隐私的SQL数据血缘分析工具
最近团队接手了一个新的数据仓库项目,这个项目已经开发了很多年,包含了几百个表和几万行 ETL 存储过程代码。 目前我们经常面临的问题包括: 这个字段从哪里来?这张表被哪些存储过程用到了?修改这个字段会影响哪些 ET…...
从多项式逼近到优化求解:泰勒展开与拉格朗日乘子的机器学习实践
1. 泰勒展开:机器学习的"局部望远镜" 第一次接触泰勒公式时,我的数学老师用了个有趣的比喻:这就像用乐高积木拼凑复杂雕塑的局部轮廓。在机器学习中,这个思想被广泛应用——当我们面对复杂的损失函数曲面时,…...
Listary vs Everything:Windows文件搜索工具终极对比(附实战技巧)
Listary vs Everything:Windows文件搜索工具终极对比(附实战技巧) 在Windows生态中,高效的文件搜索工具一直是生产力提升的关键。Listary和Everything作为两款备受推崇的解决方案,各自拥有独特的优势和使用场景。本文将…...
永磁同步电机参数辨识:EKF算法的奇妙之旅
卡尔曼滤波EKF算法,针对于永磁同步电机的电阻、电感等参数的辨识,辨识速度快,效果好,适合入门童鞋参考学习:本商品 包含以下内容: (1)采用SVPWM矢量控制; (2&…...
原创:黄大年茶思屋难题揭榜第141期|5道核心题精简公开·未获技术反馈求指正
黄大年茶思屋难题揭榜第141期|5道核心题精简公开未获技术反馈求指正 作者:华夏之光永存 摘要 这五道题我们已完整解题并提交黄大年茶思屋难题揭榜,最终被退回,但平台未给出任何具体技术驳回意见、未指明缺陷、未提供修改方向。我们…...
TikTok音乐提取全攻略:3分钟学会用DouK-Downloader分离音频
TikTok音乐提取全攻略:3分钟学会用DouK-Downloader分离音频 【免费下载链接】TikTokDownloader JoeanAmier/TikTokDownloader: 这是一个用于从TikTok下载视频和音频的工具。适合用于需要从TikTok下载视频和音频的场景。特点:易于使用,支持多种…...
