# rpc-frontend **Repository Path**: dennis-kk/rpc-frontend ## Basic Information - **Project Name**: rpc-frontend - **Description**: IDL文件生成前端 - **Primary Language**: C++ - **License**: MIT - **Default Branch**: v0.4.0-alpha - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 6 - **Created**: 2019-12-05 - **Last Updated**: 2023-09-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## IDL转换工具 将IDL文件转换为通用JSON中间格式,方便使用任何支持JSON访问的语言用来生成RPC框架代码 ### 使用步骤 1. 定义IDL文件 2. 导出为JSON文件 ## IDL文件规则 ### 1. 文件命名规范 > idl文件的命名采全小写不准带下划线。 ### 2. IDL文件内部定义 > IDL文件内部一共包含三个部分,分别是:enum , struct 和 service #### 2.1 关键字import > 当有多个IDL文件时,可以将struct和service组织在不同的文件内,将要使用的文件通过#import来导入到入口文件。 ```idl // 语法 在idl文件的最上方,类似c++的头文件的使用方式 #import "shop.idl" #import "item.idl" ``` #### 2.2 enum > enum 枚举 0 已经被框架占用 用户定义的默认从1开始 ```idl enum ErrorCode{ SUCCESS, INVALIDSCENE, INVALIDPOSITION, } ``` #### 2.3 struct > struct是纯数据结构,不支持定义方法,允许struct内部定义struct。 ##### 2.3.1 数据类型 目前struct 内支持的数据类型包含以下15种: | 数据类型 | 描述 | | -------- | -------------- | | i8 | 8位有符号整数 | | i16 | 16位有符号整数 | | i32 | 32位有符号整数 | | i64 | 64位有符号整数 | | ui8 | 8位无符号整数 | | ui16 | 16位无符号整数 | | ui32 | 32位无符号整数 | | ui64 | 64位无符号整数 | | string | 字符串 | | bool | 布尔 | | float | 单精度浮点数 | | double | 双精度浮点数 | | dict | 字典 | | set | 集合 | | seq | 序列(数组) | ##### 2.3.2 命名规范 struct内部变量的命名规范: 1. 命名需要有意义。 2. 变量名全小写,单词和单词之间用下划线分开。 3. 对于结构体内大写的字段会在生成的时候,主动转化为小写 ```idl // example struct Item{ ui64 item_uid string item_name ui32 item_count } struct A { struct B { ... } } ``` 所有定义的struct都为全局作用域,不论是否定义在任何一个struct内部,还是service内部。struct不要定义在service内部。 #### 2.4 service > service为接口定义,接口内可以包含若干方法。 ##### 2.4.1 服务类型 目前修饰service的关键字一共有以下四种: 1. 单件 (single) :同一时刻工厂只会创建一个实例 2. 多实例 (multiple=n) :同时可以有多个实例存在,一个进程内会多次创建服务的示例。 3. 可重入 (reentrant) :单个实例但可以被同时调用 4. 通用的 (generic) : 主要是给lua服务器使用 5. 静态 (static),动态 (dynamic) :服务器是否可以被动态加载,不加这个关键字的时候默认是static ```idl // 做多可以生成16个实例 service BuyItem multiple=16 { } // 单件,只能有一个实例 service ShellItem single { } // 单件,只能有一个实例,但可以被并发调用 service Shop reentrant { } // 单件,只能有一个实例,但可以被并发调用,同时是动态加载 service dynamic Mall reentrant { } // lua的动态服务 service dynamic Scene generic { [script_type:lua] } ``` ##### 2.4.2 方法类型 1. 双工 :代理调用后会等待返回(不论方法是否有返回值) 2. 单工 (oneway) :代理调用后不会等待返回,也不关心调用成功或者失败,相当于通知 ```c++ service Shop multiple=16 { oneway void SyncItem(Item) } ``` ##### 2.4.3 方法超时和重试 1. 双工服务方法默认有5秒的超时时间,默认不重试 2. 超时时间和重试次数是可以配置的 ```c++ service Shop multiple=16 { void Buy(Data,string) timeout=2000 retry=3 } ``` 以上的配置为超时2秒,最多重试3次 ##### 2.4.4 命名规范 service内部变量的命名规范: 1. 命名需要有意义。 2. service 名字,用[驼峰命名规则](https://en.wikipedia.org/wiki/Camel_case)。 3. service 内部的方法,用[驼峰命名规则](https://en.wikipedia.org/wiki/Camel_case)。 ```c++ service Shop multiple=16 { void Buy(item) timeout=2000 retry=3 oneway void SyncItem(Item) } ``` ##### 2.4.5 服务标记 服务可以添加标记,标记用于区分生成代码的语言。用法[key:value1, value2,...,valuen] (value为语言名称,例如: cpp , csharp , lua) 目前key只支持两个关键字: script_type 和 no_service。 - script_type :需要生成value语言脚本类型,目前支持lua。 - no_service :不支持生成 value 语言的服务, 有所语言都支持。 ```idl service dynamic Scene generic { // 需要生成lua的脚本 [script_type:lua] } service dynamic Scene multiple=18 { // 不会生成csharp [no_service:csharp] } ``` ### 3.注释 idl文件支持单行注释和多行注释。 ```idl // 这是个单行注释 /* * 这是个多行注释 */ ``` ## 生成JSON文件 frontend是一个命令行工具,运行help可以得到使用方法 ![输入图片说明](https://images.gitee.com/uploads/images/2019/1212/190826_5e4267b7_467198.png "屏幕截图.png") 运行命令后可以得到对应类型的JSON文件,后续开发这可以使用这个JSON文件来生成自己的RPC框架代码,生成的构成已经进行对IDL做了语法检查和错误校验。 ![输入图片说明](https://images.gitee.com/uploads/images/2019/1212/165343_8536f197_467198.png "屏幕截图.png") 可以通过 -i 或者--include 添加 你自己的import文件搜索路径 例子如下 ```shell ./frontend -f test1.idl -t cpp -i ../example ``` 上面的例子所生成的JSON文件如下: ``` ./frontend -f test1.idl -t cpp ``` ```json { "serviceNames" : [ "Service" ], "services" : [ { "methods" : [ { "arguments" : [ { "isStruct" : true,{ "enumNames" : [ "ErrorCode" ], "enums" : [ { "fields" : [ { "name" : "SUCCESS", "value" : 1 }, { "name" : "FAILD", "value" : 2 } ], "name" : "ErrorCode" } ], "idlname" : "test1", "serviceNames" : [ "Service", "ServiceDynamic", "MyService", "Lua" ], "services" : [ { "loadType" : "static", "methods" : [ { "arguments" : [ { "IdlType" : "struct", "index" : 1, "isStruct" : true, "type" : "Data" }, { "IdlType" : "string", "index" : 2, "type" : "std::string" } ], "index" : 1, "is_stream" : false, "name" : "method1", "noexcept" : false, "oneway" : true, "retType" : { "IdlType" : "void", "type" : "void" } }, { "arguments" : [ { "IdlType" : "i8", "index" : 1, "type" : "std::int8_t" }, { "IdlType" : "set", "index" : 2, "key" : { "IdlType" : "string", "type" : "std::string" }, "type" : "std::unordered_set" }, { "IdlType" : "ui64", "index" : 3, "type" : "std::uint64_t" } ], "index" : 2, "is_stream" : false, "name" : "method2", "noexcept" : false, "retType" : { "IdlType" : "string", "type" : "std::string" }, "timeout" : 5000 } ], "name" : "Service", "type" : "single", "uuid" : "9046620621498282749" }, { "loadType" : "dynamic", "methods" : [ { "arguments" : [ { "IdlType" : "i8", "index" : 1, "type" : "std::int8_t" }, { "IdlType" : "set", "index" : 2, "key" : { "IdlType" : "string", "type" : "std::string" }, "type" : "std::unordered_set" }, { "IdlType" : "ui64", "index" : 3, "type" : "std::uint64_t" } ], "index" : 1, "is_stream" : false, "name" : "method1", "noexcept" : false, "retType" : { "IdlType" : "string", "type" : "std::string" }, "retry" : 3, "timeout" : 2000 } ], "name" : "ServiceDynamic", "type" : "reentrant", "uuid" : "9046620621990182746" }, { "loadType" : "dynamic", "maxInst" : 16, "methods" : [ { "arguments" : [ { "IdlType" : "void", "index" : 1, "type" : "void" } ], "index" : 1, "is_stream" : false, "name" : "method14", "noexcept" : false, "retType" : { "IdlType" : "struct", "isStruct" : true, "type" : "Dummy" }, "timeout" : 5000 }, { "arguments" : [ { "IdlType" : "void", "index" : 1, "type" : "void" } ], "index" : 2, "is_stream" : false, "name" : "method1", "noexcept" : false, "retType" : { "IdlType" : "seq", "key" : { "IdlType" : "struct", "isStruct" : true, "type" : "Data" }, "type" : "std::vector" }, "timeout" : 5000 }, { "arguments" : [ { "IdlType" : "void", "index" : 1, "type" : "void" } ], "index" : 3, "is_stream" : false, "name" : "method2", "noexcept" : false, "retType" : { "IdlType" : "dict", "key" : { "IdlType" : "ui32", "type" : "std::uint32_t" }, "type" : "std::unordered_map", "value" : { "IdlType" : "struct", "isStruct" : true, "type" : "Data" } }, "timeout" : 5000 } ], "name" : "MyService", "notations" : [ { "no_service" : [ "csharp" ] } ], "type" : "multiple", "uuid" : "9046620621385673117" }, { "loadType" : "dynamic", "methods" : [ { "arguments" : [ { "IdlType" : "string", "index" : 1, "type" : "std::string" }, { "IdlType" : "string", "index" : 2, "type" : "std::string" } ], "index" : 1, "is_stream" : false, "name" : "login", "noexcept" : false, "retType" : { "IdlType" : "ui64", "type" : "std::uint64_t" }, "timeout" : 5000 }, { "arguments" : [ { "IdlType" : "ui64", "index" : 1, "type" : "std::uint64_t" } ], "index" : 2, "is_stream" : false, "name" : "logout", "noexcept" : false, "retType" : { "IdlType" : "void", "type" : "void" }, "timeout" : 5000 }, { "arguments" : [ { "IdlType" : "void", "index" : 1, "type" : "void" } ], "index" : 3, "is_stream" : false, "name" : "oneway_method", "noexcept" : false, "oneway" : true, "retType" : { "IdlType" : "void", "type" : "void" } } ], "name" : "Lua", "notations" : [ { "script_type" : [ "lua" ] } ], "type" : "generic", "uuid" : "9046620620658582252" } ], "structNames" : [ "Dummy", "Data" ], "structs" : [ { "fields" : [ { "IdlType" : "dict", "index" : 1, "key" : { "IdlType" : "i64", "type" : "std::int64_t" }, "name" : "field1", "type" : "std::unordered_map", "value" : { "IdlType" : "string", "type" : "std::string" } }, { "IdlType" : "enum", "index" : 2, "isEnum" : true, "name" : "error", "type" : "ErrorCode" } ], "name" : "Dummy" }, { "fields" : [ { "IdlType" : "dict", "index" : 1, "key" : { "IdlType" : "i64", "type" : "std::int64_t" }, "name" : "field1", "type" : "std::unordered_map", "value" : { "IdlType" : "string", "type" : "std::string" } }, { "IdlType" : "struct", "index" : 2, "isStruct" : true, "name" : "field3", "type" : "Dummy" }, { "IdlType" : "seq", "index" : 3, "key" : { "IdlType" : "struct", "isStruct" : true, "type" : "Dummy" }, "name" : "field4", "type" : "std::vector" }, { "IdlType" : "dict", "index" : 4, "key" : { "IdlType" : "i64", "type" : "std::int64_t" }, "name" : "field6", "type" : "std::unordered_map", "value" : { "IdlType" : "struct", "isStruct" : true, "type" : "Dummy" } } ], "name" : "Data" } ] } "type" : "Data" }, { "type" : "std::string" } ], "name" : "method1", "retType" : { "type" : "void" } }, { "arguments" : [ { "type" : "std::int8_t" }, { "key" : { "type" : "std::string" }, "type" : "std::unordered_set" }, { "type" : "std::uint64_t" } ], "name" : "method2", "retType" : { "type" : "std::string" } } ], "name" : "Service" } ], "structNames" : [ "Data" ], "structs" : [ { "fields" : [ { "name" : "field1", "type" : "std::int32_t" }, { "name" : "field2", "type" : "std::string" }, { "key" : { "type" : "std::string" }, "name" : "field3", "type" : "std::vector" }, { "key" : { "type" : "std::string" }, "name" : "field4", "type" : "std::unordered_set" }, { "key" : { "type" : "std::int64_t" }, "name" : "field5", "type" : "std::unordered_map", "value" : { "type" : "std::string" } }, { "name" : "field6", "type" : "bool" }, { "name" : "field7", "type" : "float" }, { "name" : "field8", "type" : "double" } ], "name" : "Data" } ] } ```