{"id":2605225,"url":"https://github.com/pearu/simple-rpc-cpp","last_synced_at":"2025-09-11T10:42:50.119Z","repository":{"id":35953928,"uuid":"40243625","full_name":"pearu/simple-rpc-cpp","owner":"pearu","description":"a simple RPC wrapper generator to C/C++ functions","archived":false,"fork":false,"pushed_at":"2015-08-05T12:50:44.000Z","size":168,"stargazers_count":38,"open_issues_count":1,"forks_count":9,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-28T18:21:20.556Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pearu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-05T12:19:42.000Z","updated_at":"2025-02-26T14:56:03.000Z","dependencies_parsed_at":"2022-09-14T02:40:45.830Z","dependency_job_id":null,"html_url":"https://github.com/pearu/simple-rpc-cpp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pearu%2Fsimple-rpc-cpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pearu%2Fsimple-rpc-cpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pearu%2Fsimple-rpc-cpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pearu%2Fsimple-rpc-cpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pearu","download_url":"https://codeload.github.com/pearu/simple-rpc-cpp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249026733,"owners_count":21200499,"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":[],"created_at":"2024-01-27T19:25:18.239Z","updated_at":"2025-04-15T07:31:09.981Z","avatar_url":"https://github.com/pearu.png","language":"Python","readme":"This project initiated from the following practical problem. To control experimental equipment via computers, manufactures provide software drivers with SDK written in C/C++. Unfortunately, Windows platform is often the only supported platform or support for other platforms stays years behind. In order to control such equipment from a Linux platform, for instance, Remote Procedure Calling (RPC) techniques can be used.\n\n_Simple RPC C++_ project provides a Python script that generates wrappers to C/C++ functions and RPC server applications so that the wrapped C/C++ functions could be called from an application (local host) but the C/C++ functions are executed on a server application (remote host).\n\nThe usage of word \"simple\" in the name of this project is due to the following:\n\n  * _RPC technology can be simple to use_ --- editing existing code should be minimal in order to remotely call C/C++ functions. Just changing the name of a header file should be sufficient to adapt an application to use RPC for certain C/C++ functions. Note that existing RPC libraries require RPC specific client applications; the current project aims at requiring minimal modification to client applications so that switching from calling C/C++ functions directly or via RPC, would be straightforward.\n\n  * _Simplification can be sufficient for practical applications_ --- C/C++ functions that can be wrapped for RPC, are assumed to have \"simple\" prototypes, that is, the arguments should have types that Boost serialization library can handle. This includes all standard C/C++ scalar types and standard STL collections. These types can be defined in arguments as is, or as references, or as pointers. Notice that pointer arguments are treated in application program (in local host) as scalars that can be passed to RPC server program where they point to actual memory location of the remote host.\n\n  * _Simplicity goes with restrictions_ --- For instance, wrapping C++ template functions is not supported. In addition, when running an application and RPC server on hosts with different architecture or operating system, special care must be taken to ensure that the data exchange between local and remote host is correct. For instance, the size of standard C/C++ `int` type may be different on local and remote hosts leading to possible corruption of data. To avoid this, always use scalar types with fixed byte width, for instance, `int32_t`, `uint64_t`, etc. Finally, no care is taken when the endian of local and remote hosts differ..\n\n# Installation #\n\nThe project assumes availability of Python 2.x. Python 3.x support might require minor modifications in the project source code, patches are welcome.\n\nCheckout the project source code, see [Source/Checkout](https://code.google.com/p/simple-rpc-cpp/source/checkout) for instructions. In the source code directory, run\n```\nsudo python setup.py install\r\n```\nWindows users should run `python setup.py install` from command prompt.\n\n\nTo verify success, execute\n```\n  cd tests\r\n  make\r\n```\nIf the tests pass, you can try out the \"Example\" project below.\n\n# Example #\n\nA typical C/C++ project consists of three parts: application source file containing the `main` function, source file(s) of computational functions, and header file(s) of the corresponding prototypes.\nAll source files are compiled and linked together resulting an application program.\nWhen running this application program, the `main` function calls computational functions\nand outputs the results. Our aim is that when `main` function calls computational functions then they are actually executed in remote host. For that we use RPC technique to send function arguments and then receive function results over network. The current project _Simple RPC C++_ provides a Python script `simple_rpc` that constructs RPC wrapper functions to computational functions and generates the corresponding RPC source code. By design, modifications to existing source files are minimal.\nIn fact, in a typical usage case only the application source file requires minor editing while no modifications are needed to the rest of source or header files, as will be demonstrated below.\n\nTo illustrate this, consider the following example project consisting of three files:\n\u003ctable border='1'\u003e\n\u003ctr\u003e\n\u003cth\u003eSource file: example_dot.cpp\u003c/th\u003e\n\u003cth\u003eHeader file: example_dot.hpp\u003c/th\u003e\n\u003cth\u003eApplication source file: example_dot_app.cpp\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\u003cpre\u003e\u003ccode\u003e#include \"example_dot.hpp\"\r\u003cbr\u003e\n\r\u003cbr\u003e\ndouble dot_product(const vector\u0026lt;double\u0026gt; \u0026amp; a,\r\u003cbr\u003e\n\t\t   const vector\u0026lt;double\u0026gt; \u0026amp; b\r\u003cbr\u003e\n\t\t   )\r\u003cbr\u003e\n{\r\u003cbr\u003e\n  double sum = 0;\r\u003cbr\u003e\n  for (int i = 0; i \u0026lt; a.size(); i++)\r\u003cbr\u003e\n    sum += a[i] * b[i];\r\u003cbr\u003e\n  return sum;\r\u003cbr\u003e\n}\r\u003cbr\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd\u003e\n\u003cpre\u003e\u003ccode\u003e#ifndef EXAMPLE_DOT_HPP_DEFINED\r\u003cbr\u003e\n#define EXAMPLE_DOT_HPP_DEFINED\r\u003cbr\u003e\n\r\u003cbr\u003e\n#include \u0026lt;vector\u0026gt;\r\u003cbr\u003e\nusing namespace std;\r\u003cbr\u003e\n\r\u003cbr\u003e\ndouble dot_product(const vector\u0026lt;double\u0026gt; \u0026amp; a,\r\u003cbr\u003e\n\t\t   const vector\u0026lt;double\u0026gt; \u0026amp; b\r\u003cbr\u003e\n\t\t   );\r\u003cbr\u003e\n\r\u003cbr\u003e\n#endif\r\u003cbr\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd\u003e\n\u003cpre\u003e\u003ccode\u003e#include \u0026lt;iostream\u0026gt;\r\u003cbr\u003e\n\r\u003cbr\u003e\n#include \"example_dot.hpp\"\r\u003cbr\u003e\n\r\u003cbr\u003e\nmain()\r\u003cbr\u003e\n{\r\u003cbr\u003e\n  vector\u0026lt;double\u0026gt; a(3);\r\u003cbr\u003e\n  a[0] = 1.2; a[1] = 3.4; a[2] = 5.6;\r\u003cbr\u003e\n  cout \u0026lt;\u0026lt; \"dot_product(a,a) -\u0026gt; \";\r\u003cbr\u003e\n  cout \u0026lt;\u0026lt; dot_product(a,a) \u0026lt;\u0026lt; endl;\r\u003cbr\u003e\n}\r\u003cbr\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\nThe corresponding application can be compiled and executed:\n```\n$ c++ example_dot.cpp example_dot_app.cpp -o example_dot_app\r\n$ ./example_dot_app\r\ndot_product(a,a) -\u003e 44.36\r\n```\n\nIn order to call `dot_product` via RPC server, first, we generate wrapper codes:\n```\n$ simple_rpc example_dot.hpp\r\nCreating RPC wrappers to functions:\r\n    double dot_product(const vector\u003cdouble\u003e \u0026 a,\r\n\t\t       const vector\u003cdouble\u003e \u0026 b\r\n\t\t      )\r\ncreating file example_dot-rpc.hpp\r\ncreating file example_dot-rpc.cpp\r\ncreating file example_dot-rpc-server.cpp\r\n```\nNotice that the `simple_rpc` script takes header files for input and generates\nthree files as shown above. These files will be used to compile and build two\nexecutable programs: one for application and one for RPC server.\n\nNext, we will modify the application source code as follows.\n\u003ctable border='1'\u003e\n\u003ctr\u003e\n\u003cth\u003eSource file: example_dot.cpp\u003c/th\u003e\n\u003cth\u003eHeader file: example_dot.hpp\u003c/th\u003e\n\u003cth\u003eApplication source file: example_dot_app.cpp\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\u003cpre\u003e\u003ccode\u003e#include \"example_dot.hpp\"\r\u003cbr\u003e\n\r\u003cbr\u003e\ndouble dot_product(const vector\u0026lt;double\u0026gt; \u0026amp; a,\r\u003cbr\u003e\n\t\t   const vector\u0026lt;double\u0026gt; \u0026amp; b\r\u003cbr\u003e\n\t\t   )\r\u003cbr\u003e\n{\r\u003cbr\u003e\n  double sum = 0;\r\u003cbr\u003e\n  for (int i = 0; i \u0026lt; a.size(); i++)\r\u003cbr\u003e\n    sum += a[i] * b[i];\r\u003cbr\u003e\n  return sum;\r\u003cbr\u003e\n}\r\u003cbr\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd\u003e\n\u003cpre\u003e\u003ccode\u003e#ifndef EXAMPLE_DOT_HPP_DEFINED\r\u003cbr\u003e\n#define EXAMPLE_DOT_HPP_DEFINED\r\u003cbr\u003e\n\r\u003cbr\u003e\n#include \u0026lt;vector\u0026gt;\r\u003cbr\u003e\nusing namespace std;\r\u003cbr\u003e\n\r\u003cbr\u003e\ndouble dot_product(const vector\u0026lt;double\u0026gt; \u0026amp; a,\r\u003cbr\u003e\n\t\t   const vector\u0026lt;double\u0026gt; \u0026amp; b\r\u003cbr\u003e\n\t\t   );\r\u003cbr\u003e\n\r\u003cbr\u003e\n#endif\r\u003cbr\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd\u003e\n\u003cpre\u003e\u003ccode\u003e#include \u0026lt;iostream\u0026gt;\r\u003cbr\u003e\n\r\u003cbr\u003e\n#include \"example_dot-rpc.hpp\"              // \u0026lt;-- (1)\r\u003cbr\u003e\n\r\u003cbr\u003e\n#ifdef SimpleRPC                            // \u0026lt;-- (2)\r\u003cbr\u003e\nusing namespace simple_rpc::example_dot;    // \u0026lt;-- (2)\r\u003cbr\u003e\n#endif                                      // \u0026lt;-- (2)\r\u003cbr\u003e\n\r\u003cbr\u003e\nmain()\r\u003cbr\u003e\n{\r\u003cbr\u003e\n  SIMPLE_RPC_CONNECT(\"127.0.0.1\", 2340, 2); // \u0026lt;-- (3)\r\u003cbr\u003e\n  vector\u0026lt;double\u0026gt; a(3);\r\u003cbr\u003e\n  a[0] = 1.2; a[1] = 3.4; a[2] = 5.6;\r\u003cbr\u003e\n  cout \u0026lt;\u0026lt; \"dot_product(a,a) -\u0026gt; \";\r\u003cbr\u003e\n  cout \u0026lt;\u0026lt; dot_product(a,a) \u0026lt;\u0026lt; endl;\r\u003cbr\u003e\n}\r\u003cbr\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\nThe application source code is modified in three places indicated with `// \u003c-- (#)`:\n  1. The name of the header file is appended with `-rpc` suffix. The generated header file contains RPC wrapper functions to functions found in the original header file.\n  1. `ifdef SimpleRPC` block is inserted. This is done for convenience as it will make easy to disable (use `-DDISABLE_SIMPLE_RPC` when compiling application code) and enable RPC in the application code. Following `using namespace` declaration exposes the RPC wrapper of `compute_dot` function to current namespace. In general, RPC wrappers are defined in namespace `simple_rpc::\u003cheaderfile name\u003e`.\n  1. `SIMPLE_RPC_CONNECT` macro is used to specify the RPC server host IP, port number and debug level (0 means no debug messages are shown, increasing this number will increase verbosity). Here we use debug level 2 in order to illustrate the connection between the application code and RPC server, see below.\n\nNext,  the application and the RPC server programs must be built. In the given example\nwe use RPC server local host (the corresponding host IP is 127.0.0.1) but, in general,\nthe application program must be built on local host while the RPC server program on\nserver host, especially, if these hosts run different operating systems.\nThe following table illustrates the build process:\n\u003ctable border='1'\u003e\n\u003ctr\u003e\n\u003cth\u003eRemote host\u003c/th\u003e\n\u003cth\u003eLocal host\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\u003cpre\u003e\u003ccode\u003e$ c++ example_dot.cpp example_dot-rpc-server.cpp \\\r\u003cbr\u003e\n   -o example_dot-rpc-server -pthread \\\r\u003cbr\u003e\n   -lboost_system -lboost_serialization \\\r\u003cbr\u003e\n   -I`simple_rpc --include-dir`\r\u003cbr\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd\u003e\n\u003cpre\u003e\u003ccode\u003e$ c++ example_dot-rpc.cpp example_dot_app.cpp \\\r\u003cbr\u003e\n   -o example_dot_app-rpc -pthread \\\r\u003cbr\u003e\n   -lboost_system -lboost_serialization \\\r\u003cbr\u003e\n   -I`simple_rpc --include-dir`\r\u003cbr\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\nNotice that all source codes of functions must be compiled on remote host while the application source code with RPC wrapper source is compiled on local host.\n\nFinally, we run the RPC server in remote host, and subsequently, run the application program:\n\u003ctable border='1'\u003e\n\u003ctr\u003e\n\u003cth\u003eRemote host\u003c/th\u003e\n\u003cth\u003eLocal host\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./example_dot-rpc-server\r\u003cbr\u003e\nrpc-server[2] waits connection via port 2340...connected!\r\u003cbr\u003e\nrpc-server:read_scalar\u0026lt;j\u0026gt;(a.size) \u0026lt;- 4 bytes\r\u003cbr\u003e\nrpc-server:read_vector\u0026lt;d\u0026gt;(a) \u0026lt;- 24 bytes\r\u003cbr\u003e\nrpc-server:read_scalar\u0026lt;j\u0026gt;(b.size) \u0026lt;- 4 bytes\r\u003cbr\u003e\nrpc-server:read_vector\u0026lt;d\u0026gt;(b) \u0026lt;- 24 bytes\r\u003cbr\u003e\nrpc-server:write_buffer_list(dot_product(a, b)) -\u0026gt; 16 bytes\r\u003cbr\u003e\nrpc-server[3] waits connection via port 2340...\r\u003cbr\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./example_dot_app-rpc\r\u003cbr\u003e\nset_debug_level:write_buffer_list(set_debug_level(debug_level)) -\u0026gt; 4 bytes\r\u003cbr\u003e\ndot_product:write_buffer_list(dot_product(a, b)) -\u0026gt; 56 bytes\r\u003cbr\u003e\ndot_product:read_scalar\u0026lt;d\u0026gt;(return_value) \u0026lt;- 8 bytes\r\u003cbr\u003e\ndot_product(a,a) -\u0026gt; 44.36\r\u003cbr\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\nNotice that RPC server can run continuously and different application programs can\nexecute functions from the server. This will work only when different application\nprograms will not execute the server functions at the same time. Server will serve the first application and during the time of execution, connections to the server by other applications will be declined.\n","funding_links":[],"categories":["Inter-process communication","进程间通信"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpearu%2Fsimple-rpc-cpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpearu%2Fsimple-rpc-cpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpearu%2Fsimple-rpc-cpp/lists"}