blob: 85ce820d40284906bb2f56d0463fc90244c67b56 [file] [log] [blame]
<!-- 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&amp;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&amp;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&amp;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: &quot;server&quot;);</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 &quot;greeter.grpc.fb.h&quot;</span></div>
<div class="line"><span class="preprocessor">#include &quot;greeter_generated.h&quot;</span></div>
<div class="line"> </div>
<div class="line"><span class="preprocessor">#include &lt;grpcpp/grpcpp.h&gt;</span></div>
<div class="line"> </div>
<div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div>
<div class="line"><span class="preprocessor">#include &lt;memory&gt;</span></div>
<div class="line"><span class="preprocessor">#include &lt;string&gt;</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&lt;HelloRequest&gt; *request_msg,</div>
<div class="line"> flatbuffers::grpc::Message&lt;HelloReply&gt; *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 &quot;parse&quot; 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-&gt;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 &amp;name = request-&gt;name()-&gt;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">&quot;Hello, &quot;</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&lt;T&gt;()` 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&lt;HelloReply&gt;();</div>
<div class="line"> assert(response_msg-&gt;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&lt;ManyHellosRequest&gt; *request_msg,</div>
<div class="line"> grpc::ServerWriter&lt;flatbuffers::grpc::Message&lt;HelloReply&gt;&gt; *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-&gt;GetRoot();</div>
<div class="line"> <span class="keyword">const</span> std::string &amp;name = request-&gt;name()-&gt;str();</div>
<div class="line"> <span class="keywordtype">int</span> num_greetings = request-&gt;num_greetings();</div>
<div class="line"> </div>
<div class="line"> <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; num_greetings; i++) {</div>
<div class="line"> <span class="keyword">auto</span> msg_offset = mb_.CreateString(<span class="stringliteral">&quot;Many hellos, &quot;</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-&gt;Write(mb_.ReleaseMessage&lt;HelloReply&gt;());</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">&quot;0.0.0.0:50051&quot;</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(&amp;service);</div>
<div class="line"> std::unique_ptr&lt;grpc::Server&gt; server(builder.BuildAndStart());</div>
<div class="line"> std::cerr &lt;&lt; <span class="stringliteral">&quot;Server listening on &quot;</span> &lt;&lt; server_address &lt;&lt; std::endl;</div>
<div class="line"> </div>
<div class="line"> server-&gt;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 &quot;greeter.grpc.fb.h&quot;</span></div>
<div class="line"><span class="preprocessor">#include &quot;greeter_generated.h&quot;</span></div>
<div class="line"> </div>
<div class="line"><span class="preprocessor">#include &lt;grpcpp/grpcpp.h&gt;</span></div>
<div class="line"> </div>
<div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div>
<div class="line"><span class="preprocessor">#include &lt;memory&gt;</span></div>
<div class="line"><span class="preprocessor">#include &lt;string&gt;</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&lt;grpc::Channel&gt; 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 &amp;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&lt;HelloRequest&gt;();</div>
<div class="line"> </div>
<div class="line"> flatbuffers::grpc::Message&lt;HelloReply&gt; 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_-&gt;SayHello(&amp;context, request_msg, &amp;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-&gt;message()-&gt;str();</div>
<div class="line"> } <span class="keywordflow">else</span> {</div>
<div class="line"> std::cerr &lt;&lt; status.error_code() &lt;&lt; <span class="stringliteral">&quot;: &quot;</span> &lt;&lt; status.error_message()</div>
<div class="line"> &lt;&lt; std::endl;</div>
<div class="line"> <span class="keywordflow">return</span> <span class="stringliteral">&quot;RPC failed&quot;</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 &amp;name, <span class="keywordtype">int</span> num_greetings,</div>
<div class="line"> std::function&lt;<span class="keywordtype">void</span>(<span class="keyword">const</span> std::string &amp;)&gt; 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&lt;ManyHellosRequest&gt;();</div>
<div class="line"> </div>
<div class="line"> flatbuffers::grpc::Message&lt;HelloReply&gt; 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_-&gt;SayManyHellos(&amp;context, request_msg);</div>
<div class="line"> <span class="keywordflow">while</span> (stream-&gt;Read(&amp;response_msg)) {</div>
<div class="line"> <span class="keyword">const</span> HelloReply *response = response_msg.GetRoot();</div>
<div class="line"> callback(response-&gt;message()-&gt;str());</div>
<div class="line"> }</div>
<div class="line"> <span class="keyword">auto</span> status = stream-&gt;Finish();</div>
<div class="line"> <span class="keywordflow">if</span> (!status.ok()) {</div>
<div class="line"> std::cerr &lt;&lt; status.error_code() &lt;&lt; <span class="stringliteral">&quot;: &quot;</span> &lt;&lt; status.error_message()</div>
<div class="line"> &lt;&lt; std::endl;</div>
<div class="line"> callback(<span class="stringliteral">&quot;RPC failed&quot;</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&lt;Greeter::Stub&gt; 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">&quot;localhost:50051&quot;</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">&quot;world&quot;</span>);</div>
<div class="line"> </div>
<div class="line"> std::string message = greeter.SayHello(name);</div>
<div class="line"> std::cerr &lt;&lt; <span class="stringliteral">&quot;Greeter received: &quot;</span> &lt;&lt; message &lt;&lt; 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 &amp;message) {</div>
<div class="line"> std::cerr &lt;&lt; <span class="stringliteral">&quot;Greeter received: &quot;</span> &lt;&lt; message &lt;&lt; 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>