Sophie

Sophie

distrib > Mageia > 4 > x86_64 > by-pkgid > ba6e5e1a033bd8535c43a771ce407926 > files > 55

lib64cxx-gtk-utils2.2-devel-2.2.3-2.mga4.x86_64.rpm

<!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.8.4"/>
<title>c++-gtk-utils: Using GVariant as an opaque data type</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="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td style="padding-left: 0.5em;">
   <div id="projectname">c++-gtk-utils
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.4 -->
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
      <li class="current"><a href="pages.html"><span>Related&#160;Pages</span></a></li>
      <li><a href="modules.html"><span>Modules</span></a></li>
      <li><a href="namespaces.html"><span>Namespaces</span></a></li>
      <li><a href="annotated.html"><span>Classes</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
    </ul>
  </div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Using GVariant as an opaque data type </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>Although mainly intended for gio's dbus implementation, GVariant objects held using this library's GvarHandle class can be useful for the general passing of opaque types in C++ which are both type safe and dynamically typed (rather than statically typed like other C++ types). Using the implementation takes a little getting used to, but it is efficient and flexible for the types it can handle, which are the types used by dbus with extensions. They can be viewed as immutable type safe unions which are easily serialised for storing on disk or sending over a network.</p>
<p>Supported types comprise integer types of varying sizes, doubles and C strings, together with arrays, hash tables (dictionaries), and structs (tuples) of any of these. Provided only these types are used, GVariant is very flexible as to the ways in which the types can be combined. Variants can hold variants, and the array, dictionary (for its value argument) and tuple containers can contain variants as well as other dictionaries, arrays and tuples, and variants can optionally hold null values.</p>
<p>How these types are combined is well explained in the documentation, but how they are decomposed is less so. This gives a few tips.</p>
<p>Extracting the basic types (integers, doubles and strings) from a GVariant object is very straightforward, and comprises either using the specific extractor function for the type concerned (g_variant_get_uint32(), g_variant_get_double(), g_variant_get_string() and so forth), or by using the formatted extractor g_variant_get() with the appropriate type format string ("u". "d", "s" and so forth).</p>
<p>Extracting values from variants holding arrays, tuples and dictionaries is more complex. g_variant_get_child_value() is the key function for this, and most of the other relevant extractors for containers are just convenience wrappers for that function. g_variant_get_child_value() will extract the object(s) that the array, tuple or dictionary hold, at the position given (which will be 0 if there is only one), wrapped in another GVariant object: it also extracts a variant held by a variant: g_variant_get_variant([variant]), is just a wrapper for g_variant_get_child_value([variant], 0) with additional type checking.</p>
<p>Say you have a variant holding a tuple containing two variants, the first of which holds an int and second a string-array. The string-array can be obtained in this way:</p>
<div class="fragment"><div class="line"><span class="comment">// &#39;input&#39; is a GvarHandle object representing a variant of type</span></div>
<div class="line"><span class="comment">// &quot;(vv)&quot; which holds a tuple containing two variants, the first</span></div>
<div class="line"><span class="comment">// of which holds an int and the second a string-array</span></div>
<div class="line"></div>
<div class="line"><a class="code" href="classCgu_1_1GvarHandle.html" title="This is a handle for managing the reference count of GVariant objects. ">Cgu::GvarHandle</a> decomposed(g_variant_get_child_value(input, 1));</div>
<div class="line"><span class="comment">// &#39;decomposed&#39; now represents a variant of type &quot;v&quot; which holds</span></div>
<div class="line"><span class="comment">// a variant which holds a string-array: index 1 has taken the</span></div>
<div class="line"><span class="comment">// second object contained in the tuple</span></div>
<div class="line"></div>
<div class="line">decomposed.reset(g_variant_get_child_value(decomposed, 0));</div>
<div class="line"><span class="comment">// &#39;decomposed&#39; now represents a variant of type &quot;as&quot; which holds</span></div>
<div class="line"><span class="comment">// a string-array: we could also have used g_variant_get_variant()</span></div>
<div class="line"></div>
<div class="line">gchar** str_arr = g_variant_dup_strv(decomposed, 0);</div>
<div class="line"><span class="comment">// str_arr now holds the string-array, free it with g_strfreev()</span></div>
</div><!-- fragment --><p>g_variant_get_child_value() can also be used to extract items from an array. Thus, instead of calling g_variant_dup_strv() on the decomposed object extracted, the strings could have been manipulated in this way:</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> num = g_variant_n_children(decomposed);</div>
<div class="line"><span class="keywordflow">for</span> (<span class="keywordtype">int</span> count = 0; count &lt; num; ++count) {</div>
<div class="line">  <a class="code" href="classCgu_1_1GvarHandle.html" title="This is a handle for managing the reference count of GVariant objects. ">Cgu::GvarHandle</a> item(g_variant_get_child_value(decomposed, count));</div>
<div class="line">  std::cout &lt;&lt; g_variant_get_string(item, 0) &lt;&lt; std::endl;</div>
<div class="line">}</div>
</div><!-- fragment --><p>Alternatively, g_variant_iter_next_value() and its derivatives g_variant_iter_next() and g_variant_iter_loop() (which are all wrappers for g_variant_get_child_value()) can be used to iterate through an array without keeping a separate count variable.</p>
<p>g_variant_get_child_value() can also be used to obtain values from a hash table, for example:</p>
<div class="fragment"><div class="line"><span class="comment">// make a dictionary entry (normally this would be placed in an array)</span></div>
<div class="line"><a class="code" href="classCgu_1_1GvarHandle.html" title="This is a handle for managing the reference count of GVariant objects. ">Cgu::GvarHandle</a> entry(g_variant_new_dict_entry(g_variant_new_uint32(2),</div>
<div class="line">                                               g_variant_new_string(<span class="stringliteral">&quot;Hello&quot;</span>)));</div>
<div class="line"><span class="comment">// decompose it and print it out</span></div>
<div class="line"><a class="code" href="classCgu_1_1GvarHandle.html" title="This is a handle for managing the reference count of GVariant objects. ">Cgu::GvarHandle</a> value(g_variant_get_child_value(entry, 0));</div>
<div class="line">std::cout &lt;&lt; g_variant_get_uint32(value) &lt;&lt; std::endl;</div>
<div class="line">value.reset(g_variant_get_child_value(entry, 1));</div>
<div class="line">std::cout &lt;&lt; g_variant_get_string(value, 0) &lt;&lt; std::endl;</div>
</div><!-- fragment --><p>Many of these extraction operations can be mimicked by the formatted g_variant_get() function. Thus, in the first example above, the two variants held by 'input' in its tuple container could be obtained in this way with one call:</p>
<div class="fragment"><div class="line"><a class="code" href="classCgu_1_1GvarHandle.html" title="This is a handle for managing the reference count of GVariant objects. ">Cgu::GvarHandle</a> h1, h2;</div>
<div class="line">{</div>
<div class="line">  GVariant* a;</div>
<div class="line">  GVariant* b;</div>
<div class="line">  g_variant_get(input, <span class="stringliteral">&quot;(vv)&quot;</span>, &amp;a, &amp;b);</div>
<div class="line">  h1.<a class="code" href="classCgu_1_1GvarHandle.html#a09d1d388ad0ef26d862e3f0052a52625">reset</a>(a);</div>
<div class="line">  h2.<a class="code" href="classCgu_1_1GvarHandle.html#a09d1d388ad0ef26d862e3f0052a52625">reset</a>(b);</div>
<div class="line">}</div>
<div class="line">... use <span class="stringliteral">&#39;h1&#39;</span> and <span class="stringliteral">&#39;h2&#39;</span> ...</div>
</div><!-- fragment --> </div></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Mon Sep 16 2013 20:45:31 for c++-gtk-utils by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.4
</small></address>
</body>
</html>