c注册cpp回调函数
在C语言中注册回调函数,函数需要使用静态函数,可使用bind和function来转换
案例一:
#include <iostream>
#include <functional>
#include <string.h>
#include "http_server.h"
#include "ret_err_code.h"
#include "log_api.h"#include "file_transfer.h"
#include "request_reprogram.h"
#include "request_progress.h"#define PORT "8089"
#define HOST_INFO "http://localhost:8089"#define FILE_TRANSFER "/path/a"
#define REQUEST_REPROGRAM "/path/b"
#define REQUEST_PROGRESS "/path/c"std::mutex HttpServer::mtx;
HttpServer *HttpServer::instance = nullptr;
std::function<int32_t(struct mg_connection *conn, void *cbdata)> EcuFileTransferHandler;
std::function<int32_t(struct mg_connection *conn, void *cbdata)> RequestReprogramHandler;
std::function<int32_t(struct mg_connection *conn, void *cbdata)> RequestProgressHandler;extern "C" {int32_t EcuFileTransferHandlerWrapper(struct mg_connection *conn, void *cbdata) {if (EcuFileTransferHandler) {return EcuFileTransferHandler(conn, cbdata);}return RET_OK;}int32_t RequestReprogramHandlerWrapper(struct mg_connection *conn, void *cbdata) {if (RequestReprogramHandler) {return RequestReprogramHandler(conn, cbdata);}return RET_OK;}int32_t RequestProgressHandlerWrapper(struct mg_connection *conn, void *cbdata) {if (RequestProgressHandler) {return RequestProgressHandler(conn, cbdata);}return RET_OK;}
}HttpServer::HttpServer()
{EcuFileTransferHandler = std::bind(&EcuFileTransfer::EcuFileTransferHandler, EcuFileTransfer::GetInstance(), std::placeholders::_1, std::placeholders::_2);RequestReprogramHandler = std::bind(&RequestReprogram::RequestReprogramHandler, RequestReprogram::GetInstance(), std::placeholders::_1, std::placeholders::_2);RequestProgressHandler = std::bind(&RequestProgress::RequestProgressHandler, RequestProgress::GetInstance(), std::placeholders::_1, std::placeholders::_2);
}HttpServer* HttpServer::GetInstance(void)
{if (instance == nullptr) {std::lock_guard<std::mutex> lock(mtx);if (instance == nullptr) {instance = new HttpServer;}}return instance;
}void HttpServer::DelInstance(void)
{std::lock_guard<std::mutex> lock(mtx);if (instance) {delete instance;instance = nullptr;}
}int32_t HttpServer::SetSourcePackagePath(string path)
{sourcePackagePath = path;return RET_OK;
}int32_t HttpServer::SetTargetPackagePath(string path)
{targetPackagePath = path;return RET_OK;
}static int LogMessage(const struct mg_connection *conn, const char *message)
{puts(message);return RET_OK;
}int32_t HttpServer::Init()
{EcuFileTransfer::GetInstance()->SetSourcePackagePath(sourcePackagePath);EcuFileTransfer::GetInstance()->SetTargetPackagePath(targetPackagePath);const char *options[] = {"listening_ports",PORT,"request_timeout_ms","10000","error_log_file","error.log","enable_auth_domain_check","no",0};int err = 0;/* Check if libcivetweb has been built with all required features. */mg_init_library(MG_FEATURES_DEFAULT);if (err) {LOG_ERR("Cannot start CivetWeb - inconsistent build.\n");return RET_EINVAL;}/* Callback will print error messages to console */memset(&callbacks, 0, sizeof(callbacks));callbacks.log_message = LogMessage;/* Start CivetWeb web server */ctx = mg_start(&callbacks, 0, options);if (ctx == nullptr) {LOG_ERR("Cannot start CivetWeb - mg_start failed.");return RET_EINVAL;}/* OTA-MASTER HTTP SERVER */mg_set_request_handler(ctx, FILE_TRANSFER, EcuFileTransferHandlerWrapper, 0);mg_set_request_handler(ctx, REQUEST_REPROGRAM, RequestReprogramHandlerWrapper, 0);mg_set_request_handler(ctx, REQUEST_PROGRESS, RequestProgressHandlerWrapper, 0);return RET_OK;
}int32_t HttpServer::Deinit()
{/* Stop the server */mg_stop(ctx);return RET_OK;
}
案例二:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <functional>
#include "file_transfer.h"
#include "ret_err_code.h"
#include "cJSON.h"
#include "def_databus.h"std::mutex EcuFileTransfer::mtx;
EcuFileTransfer *EcuFileTransfer::instance = nullptr;
std::function<int32_t(const char *key, const char *filename, char *path, size_t pathlen, void *user_data)> FieldFound;
std::function<int32_t(const char *key, const char *value, size_t valuelen, void *user_data)> FieldGet;
std::function<int32_t(const char *path, long long file_size, void *user_data)> FieldStore;extern packagesListInfo ServerPackListInfo;extern "C" {int32_t FieldFoundWrapper(const char *key, const char *filename, char *path, size_t pathlen, void *user_data) {if (FieldFound) {return FieldFound(key, filename, path, pathlen, user_data);}return RET_OK;}int32_t FieldGetWrapper(const char *key, const char *value, size_t valuelen, void *user_data) {if (FieldGet) {return FieldGet(key, value, valuelen, user_data);}return RET_OK;}int32_t FieldStoreWrapper(const char *path, long long file_size, void *user_data) {if (FieldStore) {return FieldStore(path, file_size, user_data);}return RET_OK;}
}static int SendJSON(struct mg_connection *conn, cJSON *json_obj)
{char *json_str = cJSON_PrintUnformatted(json_obj);size_t json_str_len = strlen(json_str);/* Send HTTP message header */mg_send_http_ok(conn, "application/json; charset=utf-8", json_str_len);/* Send HTTP message content */mg_write(conn, json_str, json_str_len);/* Free string allocated by cJSON_Print* */cJSON_free(json_str);return (int)json_str_len;
}EcuFileTransfer::EcuFileTransfer()
{FieldFound = std::bind(&EcuFileTransfer::field_found, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);FieldGet = std::bind(&EcuFileTransfer::field_get, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);FieldStore = std::bind(&EcuFileTransfer::field_store, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
}EcuFileTransfer* EcuFileTransfer::GetInstance(void)
{if (instance == nullptr) {std::lock_guard<std::mutex> lock(mtx);if (instance == nullptr) {instance = new EcuFileTransfer;}}return instance;
}void EcuFileTransfer::DelInstance(void)
{std::lock_guard<std::mutex> lock(mtx);if (instance) {delete instance;instance = nullptr;}
}int32_t EcuFileTransfer::SetSourcePackagePath(string path)
{sourcePackagePath = path;return RET_OK;
}int32_t EcuFileTransfer::SetTargetPackagePath(string path)
{targetPackagePath = path;return RET_OK;
}int32_t EcuFileTransfer::field_found(const char *key, const char *filename, char *path, size_t pathlen, void *user_data)
{if (strcmp(key, "file")) {return MG_FORM_FIELD_STORAGE_GET;}strcat(path, file->GetFilePath().c_str());if (access(path, 0) == -1) {int flag = mkdir(path, S_IRWXU);if (flag != 0) {std::cout << "Fail to create directory. errno " << errno << std::endl;}}strcat(path, "/");strcat(path, filename);return MG_FORM_FIELD_STORAGE_STORE;
}int32_t EcuFileTransfer::field_get(const char *key, const char *value_untruncated, size_t valuelen, void *user_data)
{/* Copy the untruncated value, so string compare functions can be used. *//* The check unit test library does not have build in memcmp functions. */if (!strcmp(key, "uuid")) {string item = string(value_untruncated, valuelen);file->SetUuid(item);} else if (!strcmp(key, "ecuId")) {string item = string(value_untruncated, valuelen);file->SetEcuId(string(item));} else if (!strcmp(key, "ecuSoftCode")) {string item = string(value_untruncated, valuelen);file->SetEcuSoftCode(string(item));} else if (!strcmp(key, "ecuSoftVer")) {string item = string(value_untruncated, valuelen);file->SetEcuSoftVer(string(item));} else if (!strcmp(key, "packageType")) {string item = string(value_untruncated, valuelen);file->SetPackageType(string(item));} else if (!strcmp(key, "fileMd5")) {string item = string(value_untruncated, valuelen);file->SetFileMd5(string(item));file->SetFilePath(string(item));} else if (!strcmp(key, "packageCount")) {string item = string(value_untruncated, valuelen);file->SetPackageCount(string(item));} else if (!strcmp(key, "packageNum")) {string item = string(value_untruncated, valuelen);file->SetPackageNum(string(item));} else if (!strcmp(key, "fileCount")) {string item = string(value_untruncated, valuelen);file->SetFileCount(string(item));} else if (!strcmp(key, "fileNum")) {string item = string(value_untruncated, valuelen);file->SetFileNum(string(item));} else {}return RET_OK;
}int32_t EcuFileTransfer::field_store(const char *path, long long file_size, void *user_data)
{file->SetStoreSuccess(true);return RET_OK;
}int32_t EcuFileTransfer::EcuFileTransferHandler(struct mg_connection *conn, void *cbdata)
{const struct mg_request_info *ri = mg_get_request_info(conn);(void)cbdata; /* currently unused */if (0 != strcmp(ri->request_method, "POST")) {/* this is not a POST request */mg_send_http_error(conn, 405, "Only post method");return 405;}if (file == nullptr) {file = new EcuFile();}struct mg_form_data_handler fdh = {FieldFoundWrapper,FieldGetWrapper,FieldStoreWrapper,NULL};fdh.user_data = nullptr;string status = "100";/* Call the form handler */int ret = mg_handle_form_request(conn, &fdh);if (ret <= 0) {std::cout << "no any elem" << std::endl;}int32_t fl = atoi(file->GetFileCount().c_str());int32_t fr = atoi(file->GetFileNum().c_str());int32_t pl = atoi(file->GetPackageCount().c_str());int32_t pr = atoi(file->GetPackageNum().c_str());if (fl == fr) {string cmd = "cd " + file->GetFilePath() +" &&" + " cat * > update.zip" +" && mkdir -p " + targetPackagePath +" && unzip -o update.zip -d " + targetPackagePath +" && rm update.zip" +" && cd .." +" && rm -r " + file->GetFilePath();FILE *fp = popen(cmd.c_str(), "r");if(fp == NULL) {perror("popen error");}pclose(fp);if (file->GetStoreSuccess()) {bool repeat = false;size_t size = ServerPackListInfo.packInfo.size();for(size_t i = 0; i < size; i++) {string id = ServerPackListInfo.packInfo.at(i).ecuId;if (!id.compare(file->GetEcuId())) {repeat = true;}}if (!repeat) {struct packagesInfo info;info.ecuId = file->GetEcuId();info.ecuSoftCode = file->GetEcuSoftCode();info.ecuSoftVer = file->GetEcuSoftVer();info.packagePath = targetPackagePath;info.packageType = file->GetPackageType();ServerPackListInfo.packInfo.push_back(info);ServerPackListInfo.packageCount = ServerPackListInfo.packInfo.size();ServerPackListInfo.batchUpdateFlag = false;ServerPackListInfo.packlistStatus = 1;ServerPackListInfo.batchId = "0.0.0";ServerPackListInfo.CreateTime = 0;}}if (pl == pr) {status = "200";}}if (file != nullptr) {delete file;file = nullptr;}cJSON *obj = cJSON_CreateObject();if (!obj) {/* insufficient memory? */mg_send_http_error(conn, 500, "Server error");return 500;}cJSON_AddStringToObject(obj, "status", status.c_str());SendJSON(conn, obj);cJSON_Delete(obj);return 200;
}int32_t EcuFile::SetUuid(string id)
{uuid = id;return RET_OK;
}int32_t EcuFile::SetEcuId(string id)
{ecuId = id;return RET_OK;
}int32_t EcuFile::SetEcuSoftCode(string code)
{ecuSoftCode = code;return RET_OK;
}int32_t EcuFile::SetEcuSoftVer(string ver)
{ecuSoftVer = ver;return RET_OK;
}int32_t EcuFile::SetPackageType(string type)
{packageType = type;return RET_OK;
}int32_t EcuFile::SetFileMd5(string md5)
{fileMd5 = md5;return RET_OK;
}int32_t EcuFile::SetPackageCount(string cnt)
{packageCount = cnt;return RET_OK;
}int32_t EcuFile::SetPackageNum(string num)
{packageNum = num;return RET_OK;
}int32_t EcuFile::SetFileCount(string cnt)
{fileCount = cnt;return RET_OK;
}int32_t EcuFile::SetFileNum(string num)
{fileNum = num;return RET_OK;
}int32_t EcuFile::SetFilePath(string path)
{filePath = path.substr(0, 8);return RET_OK;
}int32_t EcuFile::SetStoreSuccess(bool success)
{storeSuccess = success;return RET_OK;
}string EcuFile::GetUuid()
{return uuid;
}string EcuFile::GetEcuId()
{return ecuId;
}string EcuFile::GetEcuSoftCode()
{return ecuSoftCode;
}string EcuFile::GetEcuSoftVer()
{return ecuSoftVer;
}string EcuFile::GetPackageType()
{return packageType;
}string EcuFile::GetFileMd5()
{return fileMd5;
}string EcuFile::GetPackageCount()
{return packageCount;
}string EcuFile::GetPackageNum()
{return packageNum;
}string EcuFile::GetFileCount()
{return fileCount;
}string EcuFile::GetFileNum()
{return fileNum;
}string EcuFile::GetFilePath()
{return filePath;
}bool EcuFile::GetStoreSuccess()
{return storeSuccess;
}
相关文章:
c注册cpp回调函数
在C语言中注册回调函数,函数需要使用静态函数,可使用bind和function来转换 案例一: #include <iostream> #include <functional> #include <string.h> #include "http_server.h" #include "ret_err_code.…...
批量将excel中字段为“八百”替换成“九百”
要批量将Excel中字段为"八百"的内容替换为"九百",您可以使用Python的openpyxl库来实现。以下是一个示例代码演示如何读取Excel文件并进行替换操作: from openpyxl import load_workbook # 打开Excel文件 wb load_workbook(your_ex…...
关于docker-compose up -d在文件下无法运行的原因以及解决方法
一、确认文件下有docker-compose.yml文件 二、解决方法 检查 Docker 服务是否运行: 使用以下命令检查 Docker 服务是否正在运行: systemctl status docker 如果 Docker 未运行,可以使用以下命令启动它: systemctl start docker …...
机器学习笔记 - 基于keras + 小型Xception网络进行图像分类
一、简述 Xception 是深度为 71 层的卷积神经网络,仅依赖于深度可分离的卷积层。 论文中将卷积神经网络中的 Inception 模块解释为常规卷积和深度可分离卷积运算(深度卷积后跟点卷积)之间的中间步骤。从这个角度来看,深度可分离卷积可以理解为具有最大数量塔的 Inception 模…...
【Unity每日一记】SceneManager场景资源动态加载
👨💻个人主页:元宇宙-秩沅 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 秩沅 原创 👨💻 收录于专栏:uni…...
自动驾驶数据回传需求
1、需求分析 用户 用户需求 实时性要求 需回传数据 数据类型 采样周期 数据量 大小 数据回传通道 研发工程师 分析评估系统性能表现,例如智驾里程统计、接管率表现、油耗表现、AEB报警次数等 当天 车身底盘数据、自动驾驶系统状态数据等 结构化数据 10…...
使用Jmeter自带recorder代理服务器录制接口脚本
脚本录制 配置线程组 添加代理服务器 端口 和 录制脚本放置位置可根据需要设置 启动录制 点击启动后 弹出创建证书提示,点击OK 这个证书后续需要使用到 然后可见 一个弹窗。 Recorder . 本质是代理服务录制交易控制 可设置对应数据 方便录制脚本的查看 证书配置…...
我和 TiDB 的故事 | 远近高低各不同
作者: ShawnYan 原文来源: https://tidb.net/blog/b41a02e6 Hi, TiDB, Again! 书接上回, 《我和 TiDB 的故事 | 横看成岭侧成峰》 ,一年时光如白驹过隙,这一年我好似在 TiDB 上投入的时间总量不是很多࿰…...
深入浅出Pytorch函数——torch.nn.init.zeros_
分类目录:《深入浅出Pytorch函数》总目录 相关文章: 深入浅出Pytorch函数——torch.nn.init.calculate_gain 深入浅出Pytorch函数——torch.nn.init.uniform_ 深入浅出Pytorch函数——torch.nn.init.normal_ 深入浅出Pytorch函数——torch.nn.init.c…...
Jenkins-发送邮件配置
在Jenkins构建执行完毕后,需要及时通知相关人员。因此在jenkins中是可以通过邮件通知的。 一、Jenkins自带的邮件通知功能 找到manage Jenkins->Configure System,进行邮件配置: 2. 配置Jenkins自带的邮箱信息 完成上面的配置后…...
网络通信原理传输层TCP三次建立连接(第四十八课)
ACK :确认号 。 是期望收到对方的下一个报文段的数据的第1个字节的序号,即上次已成功接收到的数据字节序号加1。只有ACK标识为1,此字段有效。确认号X+1SEQ:序号字段。 TCP链接中传输的数据流中每个字节都编上一个序号。序号字段的值指的是本报文段所发送的数据的第一个字节的…...
【Python机器学习】实验14 手写体卷积神经网络(PyTorch实现)
文章目录 LeNet-5网络结构(1)卷积层C1(2)池化层S1(3)卷积层C2(4)池化层S2(5)卷积层C3(6)线性层F1(7)线性层F2 …...
Debian查询硬件状态
很早以前写过一个查询树霉派硬件状态的文章,用是Python写的一个小程序。里面用到了vcgencmd这个测温度的内部命令,但这个命令在debian里面没有,debian里只有lm_sensors的外部命令,需要安装:apt-get install lm_sensors…...
除自身以外数组的乘积(c语言详解)
题目:除自身外数组的乘积 给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据保证数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请不要使用除…...
ONES × 鲁邦通|打造研发一体化平台,落地组织级流程规范
近日,ONES 签约工业互联网行业领先的解决方案提供商——鲁邦通,助力鲁邦通优化组织级流程规范,落地从需求到交付的全生命周期线上化管理。 依托于 ONES 一站式研发管理平台,鲁邦通在软硬件设计开发、项目管理和精益生产等方面的数…...
【GaussDB】 SQL 篇
建表语句 表的分类 普通的建表语句 复制表内容 只复制表结构 create table 新表名(like 源表名 including all); 如果希望注释被复制的话要指定including comments 复制索引、主键约束和唯一约束,那么需要指定including indexes including constraints …...
rn和flutter出现“Running Gradle task ‘assembleDebug
在第一次运行rn和flutter时,会卡在Running Gradle task assembleDebug,可以使用阿里的镜像,如下图: maven { url https://maven.aliyun.com/repository/google/ } google() maven { url https://maven.aliyun.com/repository/jcen…...
Shell脚本基础( 四: sed编辑器)
目录 1 简介 1.1 sed编辑器的工作流程 2 sed 2.1 基本用法 2.2 sed基本格式 2.2.1 sed支持正则表达式 2.2.2 匹配正则表达式 2.2.3 奇数偶数表示 2.2.4 -d选项删除 2.2.5 -i修改文件内容 2.2.6 -a 追加 2.3 搜索替代 2.4 变量 1 简介 sed是一种流编辑器,…...
微信消息没通知iphone can‘t show notifications
小虎最近手机微信消息没通知,本来以为要卸载,但是发现原来是多客户端登录导致消息被其他平台截取,所有没有通知。 解决方法 小虎是在手机和电脑端同时登录的,所有退出电脑端后手机新消息就有提示了。可能是一个bug。...
Linux Kernel:pid与namespace
环境: Kernel Version:Linux-5.10 ARCH:ARM64 一:前言 Linux内核涉及进程和程序的所有算法都围绕task_struct数据结构建立,具体可看另一篇文章: Linux Kernel:thread_info与task_struct 同时Linux提供了资源限制(resource limit, rlimit)机制,对进程使用系统资源施…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
