Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
原创征文
RPC远程调用
rt-thread 移植 eRPC 系列(二) 之 演示
发布于 2022-08-22 10:38:36 浏览:1322
订阅该版
[tocm] ## 前言 前一篇文章,我们简单介绍了 erpc 是何物,以及不同环境下怎么编译 erpc。今天,我们通过两个小 demo 开启 erpc 之旅。 > 注:以下均在 Linux 系统环境中操作。 ### hello eRPC #### 编辑 IDL 文件 打开终端,进入工作路径。 新建文本文件,重命名保存为 "hello.erpc"。编辑文件,添加内容: ``` program hello enum lockErrors { ERR_OK = 0, ERR_OUTMEM, ERR_MAX, } interface Hello { sayHello(binary txInput) -> binary } ``` > 注:IDL 语法见下篇文章,这里定义了一个叫 "hello" 的应用程序,仅定义了一个 "sayHello" 远程调用 api #### 生成应用代码 执行命令 `erpcgen hello.erpc` 。生成四个文件 "hello_client.cpp"、 "hello_.h"、 "hello_server.cpp"、 "hello_server.h"。 新建并编辑源码文件 "client.cpp" ``` #include
#include
#include
#include
#include
#include "hello.h" static void free_binary_t_struct(binary_t *data) { if (data->data) { erpc_free(data->data); } } int main(int argc, char *argv[]) { erpc_transport_t transport = erpc_transport_tcp_init("127.0.0.1", 5555, false); erpc_mbf_t message_buffer_factory = erpc_mbf_dynamic_init(); erpc_client_init(transport, message_buffer_factory); char *msg = "hello erpc!"; binary_t b = {(uint8_t *)msg, (uint32_t)strlen(msg)}; binary_t *resp = sayHello(&b); if (resp != NULL) { char *buf = (char *)malloc(resp->dataLength + 1); strncpy(buf, (const char *)resp->data, resp->dataLength); buf[resp->dataLength] = '\0'; printf("respond: %s\n", buf); free_binary_t_struct(resp); free(buf); } erpc_transport_tcp_close(); return 0; } ``` 客户端程序,首先初始化创建 erpc 客户端服务,然后调用 "sayHello" 远程函数,给远程传参是一个二进制数据结构(这里填充的字符串),最后打印函数执行响应结果。 新建并编辑源码文件 "server.cpp" ``` #include
#include
#include
#include
#include
#include
#include "hello_server.h" binary_t *sayHello(const binary_t *input) { struct timeval t_val; struct tm* tm_l = NULL; time_t tim_t; size_t len = 0; char *buf; printf("ServerHello called\n"); buf = (char *)malloc(input->dataLength + 21); strncpy(buf, (const char *)input->data, input->dataLength); gettimeofday(&t_val, NULL); tim_t = t_val.tv_sec; tm_l = localtime(&tim_t); len = strftime(&buf[input->dataLength], 21, "@%Y-%m-%d %H:%M:%S", tm_l); len = strlen(buf); printf("data: %lu; %s\n", len, buf); return new binary_t{(uint8_t*)buf, (uint32_t)len}; } int main(int argc, char *argv[]) { erpc_transport_t transport = erpc_transport_tcp_init("127.0.0.1", 5555, true); erpc_mbf_t message_buffer_factory = erpc_mbf_dynamic_init(); erpc_server_init(transport, message_buffer_factory); erpc_add_service_to_server(create_Hello_service()); while(1){ erpc_server_run(); } erpc_transport_tcp_close(); return 0; } ``` 首先创建服务端 erpc 服务,然后调用 "erpc_server_run" 等待客户端的调用请求。当有客户端调用 "sayHello" 函数时,服务端将接收到的字符拼接本地时间,然后再返回给客户端。参数是客户端传输给服务端的,返回值是服务端生成返回给了客户端。 > 注:服务端应用程序必须实现 `sayHello` 。这里是 "hello.erpc" 文件中定义的 `sayHello` 函数的实现 #### 编译应用程序 分别执行下面的两条命令,生成服务端和客户端程序。 ``` g++ -Wall -I. -I/usr/local/include/erpc -L/usr/local/lib hello_server.cpp server.cpp -lerpc -lpthread -o server g++ -Wall -I. -I/usr/local/include/erpc -L/usr/local/lib hello_client.cpp client.cpp -lerpc -lpthread -o client ``` > 注:其中的 erpc 库编译见上篇文章。 #### 执行程序 在一个终端里执行 `./server`, 另外一个终端里执行 `./client`。正常运行服务端打印 ``` ServerHello called data: 31; hello erpc!@2022-08-17 14:26:16 ``` 客户端响应 ``` respond: hello erpc!@2022-08-17 14:26:16 ``` 运行结果符合预期。 ![erpc_hello.gif](https://oss-club.rt-thread.org/uploads/20220822/79405eb3ca0811c3c363f4988e2faf51.gif "erpc_hello.gif") ### Matrix 乘法运算 #### 编辑 IDL 文件 matrix.erpc ``` program matrix; const int32 matrix_size = 5; type Matrix = int32[matrix_size][matrix_size]; interface MatrixServer { matrixMultiply(in Matrix matrix1, in Matrix matrix2, out Matrix result) -> void } ``` 执行命令 `erpcgen matrix.erpc`。 #### 客户端应用程序源码 ``` #include
#include
#include
#include
#include
#include "matrix.h" int main(int argc, char *argv[]) { erpc_transport_t transport = erpc_transport_tcp_init("127.0.0.1", 5555, false); erpc_mbf_t message_buffer_factory = erpc_mbf_dynamic_init(); erpc_client_init(transport, message_buffer_factory); Matrix matrix1, matrix2, result = {{0}}; for(int i = 0; i < 5; i++){ for(int j = 0; j < 5; j++){ matrix1[i][j] = j+1; matrix2[i][j] = j+1; } } printf("===== Matrix #1 =====\n"); for(int i = 0; i < 5; i++){ for(int j = 0; j < 5; j++){ printf("%08d ", matrix1[i][j]); } printf(";\n"); } printf("===== Matrix #2 =====\n"); for(int i = 0; i < 5; i++){ for(int j = 0; j < 5; j++){ printf("%08d ", matrix2[i][j]); } printf(";\n"); } // Call remote function matrixMultiply matrixMultiply(matrix1, matrix2, result); printf("===== Result Matrix =====\n"); for(int i = 0; i < 5; i++){ for(int j = 0; j < 5; j++){ printf("%08d ", result[i][j]); } printf(";\n"); } erpc_transport_tcp_close(); return 0; } ``` 客户端初始化了两个 5x5 的矩阵,并把这俩矩阵值打印输出。调用 "matrixMultiply" 后把计算结果矩阵的值打印输出。 #### 服务端程序源码 ``` #include
#include
#include
#include
#include
#include "matrix_server.h" void matrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result) { int i, j, k; printf("===== Matrix #1 =====\n"); for(int i = 0; i < 5; i++){ for(int j = 0; j < 5; j++){ printf("%08d ", matrix1[i][j]); } printf(";\n"); } printf("===== Matrix #2 =====\n"); for(int i = 0; i < 5; i++){ for(int j = 0; j < 5; j++){ printf("%08d ", matrix2[i][j]); } printf(";\n"); } memset(result, 0, sizeof(Matrix)); for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { for (k = 0; k < 5; k++) { result[i][j] += matrix1[i][k] * matrix2[k][j]; } } } } int main(int argc, char *argv[]) { erpc_transport_t transport = erpc_transport_tcp_init("127.0.0.1", 5555, true); erpc_mbf_t message_buffer_factory = erpc_mbf_dynamic_init(); erpc_server_init(transport, message_buffer_factory); erpc_add_service_to_server(create_MatrixServer_service()); while(1){ erpc_server_run(); } erpc_transport_tcp_close(); return 0; } ``` "matrixMultiply" 函数远程端实现,计算结果放到 result 里。 > 注:服务端应用程序必须实现 `matrixMultiply` 。这里是 "matrix.erpc" 文件中定义的 `matrixMultiply` 函数的实现 #### 编译并运行 客户端有打印信息输出 ``` $ ./client.exe ===== Matrix #1 ===== 00000001 00000002 00000003 00000004 00000005 ; 00000001 00000002 00000003 00000004 00000005 ; 00000001 00000002 00000003 00000004 00000005 ; 00000001 00000002 00000003 00000004 00000005 ; 00000001 00000002 00000003 00000004 00000005 ; ===== Matrix #2 ===== 00000001 00000002 00000003 00000004 00000005 ; 00000001 00000002 00000003 00000004 00000005 ; 00000001 00000002 00000003 00000004 00000005 ; 00000001 00000002 00000003 00000004 00000005 ; 00000001 00000002 00000003 00000004 00000005 ; ===== Result Matrix ===== 00000015 00000030 00000045 00000060 00000075 ; 00000015 00000030 00000045 00000060 00000075 ; 00000015 00000030 00000045 00000060 00000075 ; 00000015 00000030 00000045 00000060 00000075 ; 00000015 00000030 00000045 00000060 00000075 ; ``` 改变 #1 #2 两个矩阵值,响应的矩阵乘结果也会变。 ![erpc_matrix.gif](https://oss-club.rt-thread.org/uploads/20220822/82990c37ee88effec124593680d57251.gif "erpc_matrix.gif") ## 结束语 本篇文章旨在通过这两个小 demo 演示 eRPC 的使用操作。 首先编辑 eRPC 的 IDL 语言脚本文件;然后生成代码;最后编写客户端和服务端两边的代码。 当我们调用 `sayHello` 或者 `matrixMultiply` 函数时,就像是调用本地的函数一样,但是函数执行过程可能是本机的另外一个进程或者网络内其它计算机上运行的程序。 本文没有讲解 IDL 语法。下一篇,笔者尽可能多的讲讲 eRPC 中使用的 IDL 语法格式。 *** 相关文章 *** [rt-thread 移植 eRPC 系列(一) 之 简介](https://club.rt-thread.org/ask/article/3acf471c19f2595f.html)
9
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
出出啊
恃人不如自恃,人之为己者不如己之自为也
文章
43
回答
1516
被采纳
342
关注TA
发私信
相关文章
1
请问RT-Thread有RPC方案吗?
2
rt-thread 支持eRPC吗
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
ART-Pi
FinSH
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
cubemx
PWM
flash
packages_软件包
freemodbus
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
keil_MDK
SFUD
rt_mq_消息队列_msg_queue
C++_cpp
at_device
ulog
本月问答贡献
出出啊
1516
个答案
342
次被采纳
小小李sunny
1440
个答案
289
次被采纳
张世争
793
个答案
171
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
1
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
4
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部