{"id":19267599,"url":"https://github.com/winsoft666/veigar","last_synced_at":"2025-04-21T19:33:00.432Z","repository":{"id":208604628,"uuid":"722042745","full_name":"winsoft666/veigar","owner":"winsoft666","description":"Cross platform RPC library using shared memory.","archived":false,"fork":false,"pushed_at":"2024-10-30T05:39:12.000Z","size":4341,"stargazers_count":43,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-30T08:38:08.683Z","etag":null,"topics":["ipc","msgpack","rpc","shared-memory"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/winsoft666.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-22T10:10:17.000Z","updated_at":"2024-10-30T05:39:16.000Z","dependencies_parsed_at":"2024-02-28T03:28:16.237Z","dependency_job_id":"498827ca-7e0a-49c8-a3f3-d0a9730ccbcf","html_url":"https://github.com/winsoft666/veigar","commit_stats":null,"previous_names":["winsoft666/veigar"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/winsoft666%2Fveigar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/winsoft666%2Fveigar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/winsoft666%2Fveigar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/winsoft666%2Fveigar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/winsoft666","download_url":"https://codeload.github.com/winsoft666/veigar/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250120136,"owners_count":21378141,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ipc","msgpack","rpc","shared-memory"],"created_at":"2024-11-09T20:13:30.320Z","updated_at":"2025-04-21T19:33:00.424Z","avatar_url":"https://github.com/winsoft666.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"[ \u003e\u003e\u003e 简体中文版](README_CN.md)\r\n\r\n# Veigar\r\n\r\nVeigar is a cross platform remote procedure call (RPC) framework, supports Windows and Linux platforms.\r\n\r\nVeigar based on shared memory and only supports RPC between native processes or threads, which is the biggest difference between Veigar and other RPC frameworks such as Thrift and grpc.\r\n\r\n\u003e So far as I know, Veigar is the first open source RPC framework based on shared memory.\r\n\u003e\r\n\u003e The term 'Veigar' comes from the 'The Tiny Master of Evil' in League of Legends.\r\n\r\n**Features:**\r\n\r\n- Expose functions of your program to be called via RPC (from any language implementing msgpack-rpc).\r\n\r\n- Call functions through RPC (of programs written in any language).\r\n\r\n- No IDL to learn.\r\n\r\n- No code generation step to integrate in your build, just C++.\r\n\r\n- No concept of server and client, and each Veigar instance can call each other.\r\n\r\n- No network, port availability issue, fake availability issues of port on Windows especially.\r\n\r\n- Support 3 call methods: Synchronous, Asynchronous with Promise, Asynchronous with Callback.\r\n\r\n# Compile\r\n\r\nAlthough Veigar based on msgpack, we have included this library in the project and do not require additional installation when using it.\r\n\r\nAlthough the header file of msgpack is referenced in the public header files of Veigar, it will not contaminate your global msgpack namespace, as the namespace of msgpack in Veigar is `vegar_msgpack`.\r\n\r\nCMake can be used for compilation and build, or using [vcpkg](https://github.com/microsoft/vcpkg) to install:\r\n\r\n```bash\r\nvcpkg install veigar\r\n```\r\n\r\n# Quick Start\r\n\r\nWhen using Veigar, simply include the `include` directory in the project and link Veigar's static library.\r\n\r\n## Synchronous Call\r\n\r\nHere is an example of synchronous call:\r\n\r\n\u003e In order to make the code more concise, this example did not verify the return value of the function. Please do not do this in practical project!\r\n\r\n```cpp\r\n#include \u003ciostream\u003e\r\n#include \"veigar/veigar.h\"\r\n\r\nusing namespace veigar;\r\n\r\nint main(int argc, char** argv) {\r\n    if (argc != 3) {\r\n        return 1;\r\n    }\r\n\r\n    std::string channelName = argv[1];\r\n    std::string targetChannelName = argv[2];\r\n\r\n    Veigar vg;\r\n\r\n    vg.bind(\"echo\", [](const std::string\u0026 msg, int i, double d, std::vector\u003cuint8_t\u003e buf) {\r\n        std::string result;\r\n        // ...\r\n        return result;\r\n    });\r\n\r\n    vg.init(channelName);\r\n\r\n    std::vector\u003cuint8_t\u003e buf;\r\n    CallResult ret = vg.syncCall(targetChannelName, 100, \"echo\", \"hello\", 12, 3.14, buf);\r\n    if (ret.isSuccess()) {\r\n        std::cout \u003c\u003c ret.obj.get().as\u003cstd::string\u003e() \u003c\u003c std::endl;\r\n    }\r\n    else {\r\n        std::cout \u003c\u003c ret.errorMessage \u003c\u003c std::endl;\r\n    }\r\n\r\n    vg.uninit();\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\nEach Veigar instance has a channel name that is unique within the current computer scope. When calling the `init` function, the channel name needs to be specified for the Veigar. Veigar does not detect the uniqueness of the channel, and the caller needs to ensure the uniqueness of the channel name.\r\n\r\nIn the above example, it is necessary to specify the channel name of the current instance and the channel name of the target instance through command line parameters, such as:\r\n\r\n```bash\r\nsample.exe myself other\r\n```\r\n\r\nEach instance bind a function named `echo`, which simply returns the msg parameter string as is.\r\n\r\nBy specifying the `syncCall` function with 'target channel name', 'function name', 'function parameters', and 'timeout milliseconds', the target function can be synchronously called and the call result obtained.\r\n\r\n## Asynchronous Call with Promise\r\n\r\nAsynchronous call that with promise can be implemented using the `asyncCall` function.\r\n\r\nThe following is an example of asynchronous call with promise:\r\n\r\n```cpp\r\nstd::vector\u003cuint8_t\u003e buf;\r\nstd::shared_ptr\u003cAsyncCallResult\u003e acr = vg.asyncCall(targetChannelName, \"echo\", \"hello\", 12, 3.14, buf);\r\nif (acr-\u003esecond.valid()) {\r\n    auto waitResult = acr-\u003esecond.wait_for(std::chrono::milliseconds(100));\r\n    if (waitResult == std::future_status::timeout) {\r\n        // timeout\r\n    }\r\n    else {\r\n        CallResult ret = std::move(acr-\u003esecond.get());\r\n        if(ret.isSuccess()) {\r\n            std::cout \u003c\u003c ret.obj.get().as\u003cstd::string\u003e() \u003c\u003c std::endl;\r\n        }\r\n        else {\r\n            std::cout \u003c\u003c ret.errorMessage \u003c\u003c std::endl;\r\n        }\r\n    }\r\n}\r\n\r\nvg.releaseCall(acr-\u003efirst);\r\n```\r\n\r\nUnlike synchronous calls, the `asyncCall` function return `std::shared_ptr\u003cAsyncCallResult\u003e`, and the caller needs to call the `releaseCall` function to release resources when obtaining the `CallResult` or when the call result is no longer related.\r\n\r\n## Asynchronous Call with Callback\r\n\r\nAsynchronous call that with callback also can be implemented using the `asyncCall` function.\r\n\r\nThe following is an example of asynchronous call with callback:\r\n\r\n```cpp\r\nstd::vector\u003cuint8_t\u003e buf;\r\nvg.asyncCall([](const CallResult\u0026 cr) {\r\n    if(cr.isSuccess()) {\r\n        std::cout \u003c\u003c cr.obj.get().as\u003cstd::string\u003e() \u003c\u003c std::endl;\r\n    }\r\n    else {\r\n        std::cout \u003c\u003c cr.errorMessage \u003c\u003c std::endl;\r\n    }\r\n }, targetChannelName, \"echo\", \"hello\", 12, 3.14, buf);\r\n\r\n```\r\n\r\nThis method does not require calling the `releaseCall` function to release resources.\r\n\r\n## RPC function parameter types\r\n\r\nSupports regular C++ data types, such as:\r\n\r\n- bool\r\n- char, wchar_t\r\n- int, unsigned int, long, unsigned long, long long, unsigned long long\r\n- uint8_t, int8_t, int32_t, uint32_t, int64_t, uint64_t\r\n- float, double\r\n\r\n```cpp\r\n Veigar vg;\r\n vg.bind(\"func\", [](char c, wchar_t w, int i, int8_t j, int64_t k) {\r\n     // ......\r\n });\r\n```\r\n\r\nAlso support STL data types, such as:\r\n\r\n- std::string\r\n- std::set\r\n- std::vector\r\n- std::map\r\n- std::string_view (C++ 17)\r\n- std::optional (C++ 17)\r\n- Not support std::wstring，but we can use std::vector\u003cuint8_t\u003e to instead of std::wstring\r\n\r\n```cpp\r\n Veigar vg;\r\n vg.bind(\"func\", [](std::string s, std::vector\u003cstd::string\u003e, std::string_view v, std::map\u003cint, bool\u003e m) {\r\n     // ......\r\n });\r\n```\r\n\r\nVeigar can also support custom data types, such as:\r\n\r\n```cpp\r\n#include \"veigar/msgpack/adaptor/define.hpp\"\r\n\r\nstruct MyPoint {\r\n    int x;\r\n    int y;\r\n    MSGPACK_DEFINE(x, y);\r\n};\r\n\r\nVeigar vg;\r\nvg.bind(\"func\", [](MyPoint m) {\r\n    // ......\r\n});\r\n```\r\n\r\nThe detailed parameter binding method can be found in [tests/t_type.cpp](./tests/t_type.cpp)。\r\n\r\n# Reject exceptions\r\n\r\nI don't like exceptions, so Veigar doesn't throw errors in the form of exceptions. Veigar catch all exceptions of C++ STL and msgpack, and returns them to the caller as return values. \r\n\r\nWhen the call fails (`!ret.isSuccess()`), the error information stored in the `errorMessage` may be the exception information captured by Veigar.\r\n\r\n# Performance\r\n\r\nUse the `examples\\performance-test` program as a test case.\r\n\r\nProcess A call process B by use 4 threads and each thread calls 25000 times. On average, it consumes 12 microseconds per call (\"calling \u003c--\u003e result\").\r\n\r\n```txt\r\nUsed: 1s240ms721μs, Total: 100000 Success: 100000, Timeout: 0, Failed: 0, Average: 12μs/call.\r\n```\r\n\r\nAlthough there is still a great possibility of performance improvement for Veigar at present, but based on test results, it has far surpassed other RPC frameworks.\r\n\r\n# List of Sponsors\r\nThank you for using this project. It would be a great pleasure for me if this project can be of help to you.\r\n\r\nSpecial thanks go to the following sponsors:\r\n\r\n- sxzxs (https://github.com/sxzxs)\r\n\r\n**You can go to my Github [homepage](https://github.com/winsoft666) to make a donation.**","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwinsoft666%2Fveigar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwinsoft666%2Fveigar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwinsoft666%2Fveigar/lists"}