| <!-- HTML header for doxygen 1.8.6--> |
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| <html xmlns="http://www.w3.org/1999/xhtml"> |
| <head> |
| <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> |
| <meta http-equiv="X-UA-Compatible" content="IE=9"/> |
| <meta name="generator" content="Doxygen 1.9.1"/> |
| <title>FlatBuffers: Use in C++</title> |
| <link href="tabs.css" rel="stylesheet" type="text/css"/> |
| <script type="text/javascript" src="jquery.js"></script> |
| <script type="text/javascript" src="dynsections.js"></script> |
| <link href="navtree.css" rel="stylesheet" type="text/css"/> |
| <script type="text/javascript" src="resize.js"></script> |
| <script type="text/javascript" src="navtreedata.js"></script> |
| <script type="text/javascript" src="navtree.js"></script> |
| <link href="search/search.css" rel="stylesheet" type="text/css"/> |
| <script type="text/javascript" src="search/searchdata.js"></script> |
| <script type="text/javascript" src="search/search.js"></script> |
| <link href="doxygen.css" rel="stylesheet" type="text/css" /> |
| <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,400italic,500,500italic,700,700italic|Roboto+Mono:400,700" rel="stylesheet"> |
| <link href="style.css" rel="stylesheet" type="text/css"/> |
| </head> |
| <body> |
| <div id="top"><!-- do not remove this div, it is closed by doxygen! --> |
| <div id="titlearea" style="height: 110px;"> |
| <table cellspacing="0" cellpadding="0"> |
| <tbody> |
| <tr style="height: 56px;"> |
| <td id="commonprojectlogo"> |
| <img alt="Logo" src="fpl_logo_small.png"/> |
| </td> |
| <td style="padding-left: 0.5em;"> |
| <div id="projectname">FlatBuffers |
| </div> |
| <div style="font-size:12px;"> |
| An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>. |
| </div> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| <!-- end header part --> |
| <!-- Generated by Doxygen 1.9.1 --> |
| <script type="text/javascript"> |
| /* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */ |
| var searchBox = new SearchBox("searchBox", "search",false,'Search','.html'); |
| /* @license-end */ |
| </script> |
| <script type="text/javascript" src="menudata.js"></script> |
| <script type="text/javascript" src="menu.js"></script> |
| <script type="text/javascript"> |
| /* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */ |
| $(function() { |
| initMenu('',true,false,'search.php','Search'); |
| $(document).ready(function() { init_search(); }); |
| }); |
| /* @license-end */</script> |
| <div id="main-nav"></div> |
| </div><!-- top --> |
| <div id="side-nav" class="ui-resizable side-nav-resizable"> |
| <div id="nav-tree"> |
| <div id="nav-tree-contents"> |
| <div id="nav-sync" class="sync"></div> |
| </div> |
| </div> |
| <div id="splitbar" style="-moz-user-select:none;" |
| class="ui-resizable-handle"> |
| </div> |
| </div> |
| <script type="text/javascript"> |
| /* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */ |
| $(document).ready(function(){initNavTree('flatbuffers_grpc_guide_use_cpp.html',''); initResizable(); }); |
| /* @license-end */ |
| </script> |
| <div id="doc-content"> |
| <!-- window showing the filter options --> |
| <div id="MSearchSelectWindow" |
| onmouseover="return searchBox.OnSearchSelectShow()" |
| onmouseout="return searchBox.OnSearchSelectHide()" |
| onkeydown="return searchBox.OnSearchSelectKey(event)"> |
| </div> |
| |
| <!-- iframe showing the search results (closed by default) --> |
| <div id="MSearchResultsWindow"> |
| <iframe src="javascript:void(0)" frameborder="0" |
| name="MSearchResults" id="MSearchResults"> |
| </iframe> |
| </div> |
| |
| <div class="PageDoc"><div class="header"> |
| <div class="headertitle"> |
| <div class="title">Use in C++ </div> </div> |
| </div><!--header--> |
| <div class="contents"> |
| <div class="textblock"><p><a class="anchor" id="md_gRPC_CppUsage"></a></p> |
| <h1><a class="anchor" id="autotoc_md192"></a> |
| Before you get started</h1> |
| <p>Before diving into the FlatBuffers gRPC usage in C++, you should already be familiar with the following:</p> |
| <ul> |
| <li>FlatBuffers as a serialization format</li> |
| <li><a href="http://www.grpc.io/docs/">gRPC</a> usage</li> |
| </ul> |
| <h1><a class="anchor" id="autotoc_md193"></a> |
| Using the FlatBuffers gRPC C++ library</h1> |
| <p>NOTE: The examples below are also in the <code>grpc/samples/greeter</code> directory.</p> |
| <p>We will illustrate usage with the following schema:</p> |
| <div class="fragment"><div class="line">table HelloReply {</div> |
| <div class="line"> message:string;</div> |
| <div class="line">}</div> |
| <div class="line"> </div> |
| <div class="line">table HelloRequest {</div> |
| <div class="line"> name:string;</div> |
| <div class="line">}</div> |
| <div class="line"> </div> |
| <div class="line">table ManyHellosRequest {</div> |
| <div class="line"> name:string;</div> |
| <div class="line"> num_greetings:int;</div> |
| <div class="line">}</div> |
| <div class="line"> </div> |
| <div class="line">rpc_service Greeter {</div> |
| <div class="line"> SayHello(HelloRequest):HelloReply;</div> |
| <div class="line"> SayManyHellos(ManyHellosRequest):HelloReply (streaming: "server");</div> |
| <div class="line">}</div> |
| </div><!-- fragment --><p>When we run <code>flatc</code>, we pass in the <code>--grpc</code> option and generage an additional <code>greeter.grpc.fb.h</code> and <code>greeter.grpc.fb.cc</code>.</p> |
| <p>Example server code looks like this:</p> |
| <div class="fragment"><div class="line"><span class="preprocessor">#include "greeter.grpc.fb.h"</span></div> |
| <div class="line"><span class="preprocessor">#include "greeter_generated.h"</span></div> |
| <div class="line"> </div> |
| <div class="line"><span class="preprocessor">#include <grpcpp/grpcpp.h></span></div> |
| <div class="line"> </div> |
| <div class="line"><span class="preprocessor">#include <iostream></span></div> |
| <div class="line"><span class="preprocessor">#include <memory></span></div> |
| <div class="line"><span class="preprocessor">#include <string></span></div> |
| <div class="line"> </div> |
| <div class="line"><span class="keyword">class </span>GreeterServiceImpl final : <span class="keyword">public</span> Greeter::Service {</div> |
| <div class="line"> <span class="keyword">virtual</span> grpc::Status SayHello(</div> |
| <div class="line"> grpc::ServerContext *context,</div> |
| <div class="line"> <span class="keyword">const</span> flatbuffers::grpc::Message<HelloRequest> *request_msg,</div> |
| <div class="line"> flatbuffers::grpc::Message<HelloReply> *response_msg)<span class="keyword"> override </span>{</div> |
| <div class="line"> flatbuffers::grpc::MessageBuilder mb_;</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="comment">// We call GetRoot to "parse" the message. Verification is already</span></div> |
| <div class="line"> <span class="comment">// performed by default. See the notes below for more details.</span></div> |
| <div class="line"> <span class="keyword">const</span> HelloRequest *request = request_msg->GetRoot();</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="comment">// Fields are retrieved as usual with FlatBuffers</span></div> |
| <div class="line"> <span class="keyword">const</span> std::string &name = request->name()->str();</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="comment">// `flatbuffers::grpc::MessageBuilder` is a `FlatBufferBuilder` with a</span></div> |
| <div class="line"> <span class="comment">// special allocator for efficient gRPC buffer transfer, but otherwise</span></div> |
| <div class="line"> <span class="comment">// usage is the same as usual.</span></div> |
| <div class="line"> <span class="keyword">auto</span> msg_offset = mb_.CreateString(<span class="stringliteral">"Hello, "</span> + name);</div> |
| <div class="line"> <span class="keyword">auto</span> hello_offset = CreateHelloReply(mb_, msg_offset);</div> |
| <div class="line"> mb_.Finish(hello_offset);</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="comment">// The `ReleaseMessage<T>()` function detaches the message from the</span></div> |
| <div class="line"> <span class="comment">// builder, so we can transfer the resopnse to gRPC while simultaneously</span></div> |
| <div class="line"> <span class="comment">// detaching that memory buffer from the builer.</span></div> |
| <div class="line"> *response_msg = mb_.ReleaseMessage<HelloReply>();</div> |
| <div class="line"> assert(response_msg->Verify());</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="comment">// Return an OK status.</span></div> |
| <div class="line"> <span class="keywordflow">return</span> grpc::Status::OK;</div> |
| <div class="line"> }</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="keyword">virtual</span> grpc::Status SayManyHellos(</div> |
| <div class="line"> grpc::ServerContext *context,</div> |
| <div class="line"> <span class="keyword">const</span> flatbuffers::grpc::Message<ManyHellosRequest> *request_msg,</div> |
| <div class="line"> grpc::ServerWriter<flatbuffers::grpc::Message<HelloReply>> *writer)<span class="keyword"></span></div> |
| <div class="line"><span class="keyword"> override </span>{</div> |
| <div class="line"> <span class="comment">// The streaming usage below is simply a combination of standard gRPC</span></div> |
| <div class="line"> <span class="comment">// streaming with the FlatBuffers usage shown above.</span></div> |
| <div class="line"> <span class="keyword">const</span> ManyHellosRequest *request = request_msg->GetRoot();</div> |
| <div class="line"> <span class="keyword">const</span> std::string &name = request->name()->str();</div> |
| <div class="line"> <span class="keywordtype">int</span> num_greetings = request->num_greetings();</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i < num_greetings; i++) {</div> |
| <div class="line"> <span class="keyword">auto</span> msg_offset = mb_.CreateString(<span class="stringliteral">"Many hellos, "</span> + name);</div> |
| <div class="line"> <span class="keyword">auto</span> hello_offset = CreateHelloReply(mb_, msg_offset);</div> |
| <div class="line"> mb_.Finish(hello_offset);</div> |
| <div class="line"> writer->Write(mb_.ReleaseMessage<HelloReply>());</div> |
| <div class="line"> }</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="keywordflow">return</span> grpc::Status::OK;</div> |
| <div class="line"> }</div> |
| <div class="line"> </div> |
| <div class="line"> flatbuffers::grpc::MessageBuilder mb_;</div> |
| <div class="line">};</div> |
| <div class="line"> </div> |
| <div class="line"><span class="keywordtype">void</span> RunServer() {</div> |
| <div class="line"> std::string server_address(<span class="stringliteral">"0.0.0.0:50051"</span>);</div> |
| <div class="line"> GreeterServiceImpl service;</div> |
| <div class="line"> </div> |
| <div class="line"> grpc::ServerBuilder builder;</div> |
| <div class="line"> builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());</div> |
| <div class="line"> builder.RegisterService(&service);</div> |
| <div class="line"> std::unique_ptr<grpc::Server> server(builder.BuildAndStart());</div> |
| <div class="line"> std::cerr << <span class="stringliteral">"Server listening on "</span> << server_address << std::endl;</div> |
| <div class="line"> </div> |
| <div class="line"> server->Wait();</div> |
| <div class="line">}</div> |
| <div class="line"> </div> |
| <div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keyword">const</span> <span class="keywordtype">char</span> *argv[]) {</div> |
| <div class="line"> RunServer();</div> |
| <div class="line"> <span class="keywordflow">return</span> 0;</div> |
| <div class="line">}</div> |
| </div><!-- fragment --><p>Example client code looks like this:</p> |
| <div class="fragment"><div class="line"><span class="preprocessor">#include "greeter.grpc.fb.h"</span></div> |
| <div class="line"><span class="preprocessor">#include "greeter_generated.h"</span></div> |
| <div class="line"> </div> |
| <div class="line"><span class="preprocessor">#include <grpcpp/grpcpp.h></span></div> |
| <div class="line"> </div> |
| <div class="line"><span class="preprocessor">#include <iostream></span></div> |
| <div class="line"><span class="preprocessor">#include <memory></span></div> |
| <div class="line"><span class="preprocessor">#include <string></span></div> |
| <div class="line"> </div> |
| <div class="line"><span class="keyword">class </span>GreeterClient {</div> |
| <div class="line"> <span class="keyword">public</span>:</div> |
| <div class="line"> GreeterClient(std::shared_ptr<grpc::Channel> channel)</div> |
| <div class="line"> : stub_(Greeter::NewStub(channel)) {}</div> |
| <div class="line"> </div> |
| <div class="line"> std::string SayHello(<span class="keyword">const</span> std::string &name) {</div> |
| <div class="line"> flatbuffers::grpc::MessageBuilder mb;</div> |
| <div class="line"> <span class="keyword">auto</span> name_offset = mb.CreateString(name);</div> |
| <div class="line"> <span class="keyword">auto</span> request_offset = CreateHelloRequest(mb, name_offset);</div> |
| <div class="line"> mb.Finish(request_offset);</div> |
| <div class="line"> <span class="keyword">auto</span> request_msg = mb.ReleaseMessage<HelloRequest>();</div> |
| <div class="line"> </div> |
| <div class="line"> flatbuffers::grpc::Message<HelloReply> response_msg;</div> |
| <div class="line"> </div> |
| <div class="line"> grpc::ClientContext context;</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="keyword">auto</span> status = stub_->SayHello(&context, request_msg, &response_msg);</div> |
| <div class="line"> <span class="keywordflow">if</span> (status.ok()) {</div> |
| <div class="line"> <span class="keyword">const</span> HelloReply *response = response_msg.GetRoot();</div> |
| <div class="line"> <span class="keywordflow">return</span> response->message()->str();</div> |
| <div class="line"> } <span class="keywordflow">else</span> {</div> |
| <div class="line"> std::cerr << status.error_code() << <span class="stringliteral">": "</span> << status.error_message()</div> |
| <div class="line"> << std::endl;</div> |
| <div class="line"> <span class="keywordflow">return</span> <span class="stringliteral">"RPC failed"</span>;</div> |
| <div class="line"> }</div> |
| <div class="line"> }</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="keywordtype">void</span> SayManyHellos(<span class="keyword">const</span> std::string &name, <span class="keywordtype">int</span> num_greetings,</div> |
| <div class="line"> std::function<<span class="keywordtype">void</span>(<span class="keyword">const</span> std::string &)> callback) {</div> |
| <div class="line"> flatbuffers::grpc::MessageBuilder mb;</div> |
| <div class="line"> <span class="keyword">auto</span> name_offset = mb.CreateString(name);</div> |
| <div class="line"> <span class="keyword">auto</span> request_offset =</div> |
| <div class="line"> CreateManyHellosRequest(mb, name_offset, num_greetings);</div> |
| <div class="line"> mb.Finish(request_offset);</div> |
| <div class="line"> <span class="keyword">auto</span> request_msg = mb.ReleaseMessage<ManyHellosRequest>();</div> |
| <div class="line"> </div> |
| <div class="line"> flatbuffers::grpc::Message<HelloReply> response_msg;</div> |
| <div class="line"> </div> |
| <div class="line"> grpc::ClientContext context;</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="keyword">auto</span> stream = stub_->SayManyHellos(&context, request_msg);</div> |
| <div class="line"> <span class="keywordflow">while</span> (stream->Read(&response_msg)) {</div> |
| <div class="line"> <span class="keyword">const</span> HelloReply *response = response_msg.GetRoot();</div> |
| <div class="line"> callback(response->message()->str());</div> |
| <div class="line"> }</div> |
| <div class="line"> <span class="keyword">auto</span> status = stream->Finish();</div> |
| <div class="line"> <span class="keywordflow">if</span> (!status.ok()) {</div> |
| <div class="line"> std::cerr << status.error_code() << <span class="stringliteral">": "</span> << status.error_message()</div> |
| <div class="line"> << std::endl;</div> |
| <div class="line"> callback(<span class="stringliteral">"RPC failed"</span>);</div> |
| <div class="line"> }</div> |
| <div class="line"> }</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="keyword">private</span>:</div> |
| <div class="line"> std::unique_ptr<Greeter::Stub> stub_;</div> |
| <div class="line">};</div> |
| <div class="line"> </div> |
| <div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> **argv) {</div> |
| <div class="line"> std::string server_address(<span class="stringliteral">"localhost:50051"</span>);</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="keyword">auto</span> channel =</div> |
| <div class="line"> grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials());</div> |
| <div class="line"> GreeterClient greeter(channel);</div> |
| <div class="line"> </div> |
| <div class="line"> std::string name(<span class="stringliteral">"world"</span>);</div> |
| <div class="line"> </div> |
| <div class="line"> std::string message = greeter.SayHello(name);</div> |
| <div class="line"> std::cerr << <span class="stringliteral">"Greeter received: "</span> << message << std::endl;</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="keywordtype">int</span> num_greetings = 10;</div> |
| <div class="line"> greeter.SayManyHellos(name, num_greetings, [](<span class="keyword">const</span> std::string &message) {</div> |
| <div class="line"> std::cerr << <span class="stringliteral">"Greeter received: "</span> << message << std::endl;</div> |
| <div class="line"> });</div> |
| <div class="line"> </div> |
| <div class="line"> <span class="keywordflow">return</span> 0;</div> |
| <div class="line">}</div> |
| </div><!-- fragment --> </div></div><!-- contents --> |
| </div><!-- PageDoc --> |
| </div><!-- doc-content --> |
| <!-- Google Analytics --> |
| <script> |
| (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ |
| (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), |
| m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) |
| })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); |
| ga('create', 'UA-49880327-7', 'auto'); |
| ga('send', 'pageview'); |
| </script> |
| </body> |
| </html> |