Angelscript/docs/manual/doc_addon_serializer.html

218 lines
15 KiB
HTML
Raw Normal View History

2021-04-12 18:25:02 +00:00
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://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.18"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>AngelScript: Serializer</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>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function() { init_search(); });
/* @license-end */
</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 id="projectlogo"><img alt="Logo" src="aslogo_small.png"/></td>
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">AngelScript
</div>
</td>
<td> <div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.18 -->
<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');
/* @license-end */
</script>
</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('doc_addon_serializer.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">Serializer </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><b>Path:</b> /sdk/add_on/serializer/</p>
<p>The <code>CSerializer</code> implements support for serializing the values of global variables in a module, for example in order to reload a slightly modified version of the script without reinitializing everything. It will resolve primitives and script classes automatically, including references and handles. For application registered types, the application needs to implement callback objects to show how these should be serialized.</p>
<p>The implementation currently has some limitations:</p>
<ul>
<li>It can only serialize to memory, i.e. it is not possible to save the values to a file.</li>
<li>If the variables changed type when restoring, the serializer cannot restore the value.</li>
<li>The serializer will attempt to backup all objects, but in some cases an application may not want to backup the actual object, but only a reference to it, e.g. an internal application object referenced by the script. Currently there is no way of telling the serializer to do differently in this case.</li>
<li>If the module holds references to objects from another module it will probably fail in restoring the values.</li>
</ul>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000001">Todo:</a></b></dt><dd>Show how to serialize extra objects too. And explain about memory management for restored objects</dd></dl>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000002">Todo:</a></b></dt><dd>Explain that handles to registered types without factories will be kept as-is</dd></dl>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000003">Todo:</a></b></dt><dd>Registered pod-types do not need a special user type as the serializer will simply keep a bitwise copy</dd></dl>
<h1><a class="anchor" id="doc_addon_serializer_1"></a>
Public C++ interface</h1>
<div class="fragment"><div class="line"><span class="keyword">class </span>CSerializer</div>
<div class="line">{</div>
<div class="line"><span class="keyword">public</span>:</div>
<div class="line"> CSerializer();</div>
<div class="line"> ~CSerializer();</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Add implementation for serializing user types</span></div>
<div class="line"> <span class="keywordtype">void</span> AddUserType(CUserType *ref, <span class="keyword">const</span> std::string &amp;name);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Store all global variables in the module</span></div>
<div class="line"> <span class="keywordtype">int</span> Store(<a class="code" href="classas_i_script_module.html">asIScriptModule</a> *mod);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Restore all global variables after reloading script</span></div>
<div class="line"> <span class="keywordtype">int</span> Restore(<a class="code" href="classas_i_script_module.html">asIScriptModule</a> *mod);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Store extra objects that are not seen from the module&#39;s global variables</span></div>
<div class="line"> <span class="keywordtype">void</span> AddExtraObjectToStore(<a class="code" href="classas_i_script_object.html">asIScriptObject</a> *<span class="keywordtype">object</span>);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Return new pointer to restored object</span></div>
<div class="line"> <span class="keywordtype">void</span> *GetPointerToRestoredObject(<span class="keywordtype">void</span> *originalObject);</div>
<div class="line">};</div>
</div><!-- fragment --><h1><a class="anchor" id="doc_addon_serializer_2"></a>
Example usage</h1>
<div class="fragment"><div class="line"><span class="keyword">struct </span>CStringType;</div>
<div class="line"><span class="keyword">struct </span>CArrayType;</div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">void</span> RecompileModule(<a class="code" href="classas_i_script_engine.html">asIScriptEngine</a> *engine, <a class="code" href="classas_i_script_module.html">asIScriptModule</a> *mod)</div>
<div class="line">{</div>
<div class="line"> <span class="keywordtype">string</span> modName = mod-&gt;<a class="code" href="classas_i_script_module.html#a4967db3ed89836ac2f3b529c499d473d">GetName</a>();</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Tell the serializer how the user types should be serialized</span></div>
<div class="line"> <span class="comment">// by adding the implementations of the CUserType interface</span></div>
<div class="line"> CSerializer backup;</div>
<div class="line"> backup.AddUserType(<span class="keyword">new</span> CStringType(), <span class="stringliteral">&quot;string&quot;</span>);</div>
<div class="line"> backup.AddUserType(<span class="keyword">new</span> CArrayType(), <span class="stringliteral">&quot;array&quot;</span>);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Backup the values of the global variables</span></div>
<div class="line"> backup.Store(mod);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Application can now recompile the module</span></div>
<div class="line"> CompileModule(modName);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Restore the values of the global variables in the new module</span></div>
<div class="line"> mod = engine-&gt;<a class="code" href="classas_i_script_engine.html#a9f7cdc52b59034e6e55eb8a56b427aa4">GetModule</a>(modName.c_str(), <a class="code" href="angelscript_8h.html#ae4cf50de5273eb8c03c6e91e6e014f0ca2feb963eb04c221e251867bc3a93d79d">asGM_ONLY_IF_EXISTS</a>);</div>
<div class="line"> backup.Restore(mod);</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="comment">// This serializes the std::string type</span></div>
<div class="line"><span class="keyword">struct </span>CStringType : <span class="keyword">public</span> CUserType</div>
<div class="line">{</div>
<div class="line"> <span class="keywordtype">void</span> Store(CSerializedValue *val, <span class="keywordtype">void</span> *ptr)</div>
<div class="line"> {</div>
<div class="line"> val-&gt;SetUserData(<span class="keyword">new</span> std::string(*(std::string*)ptr));</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordtype">void</span> Restore(CSerializedValue *val, <span class="keywordtype">void</span> *ptr)</div>
<div class="line"> {</div>
<div class="line"> std::string *buffer = (std::string*)val-&gt;GetUserData();</div>
<div class="line"> *(std::string*)ptr = *buffer;</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordtype">void</span> CleanupUserData(CSerializedValue *val)</div>
<div class="line"> {</div>
<div class="line"> std::string *buffer = (std::string*)val-&gt;GetUserData();</div>
<div class="line"> <span class="keyword">delete</span> buffer;</div>
<div class="line"> }</div>
<div class="line">};</div>
<div class="line"> </div>
<div class="line"><span class="comment">// This serializes the CScriptArray type</span></div>
<div class="line"><span class="keyword">struct </span>CArrayType : <span class="keyword">public</span> CUserType</div>
<div class="line">{</div>
<div class="line"> <span class="keywordtype">void</span> Store(CSerializedValue *val, <span class="keywordtype">void</span> *ptr)</div>
<div class="line"> {</div>
<div class="line"> CScriptArray *arr = (CScriptArray*)ptr;</div>
<div class="line"> </div>
<div class="line"> <span class="keywordflow">for</span>( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i = 0; i &lt; arr-&gt;GetSize(); i++ )</div>
<div class="line"> val-&gt;m_children.push_back(<span class="keyword">new</span> CSerializedValue(val ,<span class="stringliteral">&quot;&quot;</span>, <span class="stringliteral">&quot;&quot;</span>, arr-&gt;At(i), arr-&gt;GetElementTypeId()));</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordtype">void</span> Restore(CSerializedValue *val, <span class="keywordtype">void</span> *ptr)</div>
<div class="line"> {</div>
<div class="line"> CScriptArray *arr = (CScriptArray*)ptr;</div>
<div class="line"> arr-&gt;Resize(<a class="code" href="angelscript_8h.html#ac8186f029686800b7ce36bde4a55c815">asUINT</a>(val-&gt;m_children.size()));</div>
<div class="line"> </div>
<div class="line"> <span class="keywordflow">for</span>( <span class="keywordtype">size_t</span> i = 0; i &lt; val-&gt;m_children.size(); ++i )</div>
<div class="line"> val-&gt;m_children[i]-&gt;Restore(arr-&gt;At(<a class="code" href="angelscript_8h.html#ac8186f029686800b7ce36bde4a55c815">asUINT</a>(i)), arr-&gt;GetElementTypeId());</div>
<div class="line"> }</div>
<div class="line">};</div>
</div><!-- fragment --> </div></div><!-- contents -->
</div><!-- PageDoc -->
</div><!-- doc-content -->
<div class="ttc" id="aclassas_i_script_engine_html_a9f7cdc52b59034e6e55eb8a56b427aa4"><div class="ttname"><a href="classas_i_script_engine.html#a9f7cdc52b59034e6e55eb8a56b427aa4">asIScriptEngine::GetModule</a></div><div class="ttdeci">virtual asIScriptModule * GetModule(const char *module, asEGMFlags flag=asGM_ONLY_IF_EXISTS)=0</div><div class="ttdoc">Return an interface pointer to the module.</div></div>
<div class="ttc" id="aclassas_i_script_engine_html"><div class="ttname"><a href="classas_i_script_engine.html">asIScriptEngine</a></div><div class="ttdoc">The engine interface.</div><div class="ttdef"><b>Definition:</b> angelscript.h:1092</div></div>
<div class="ttc" id="aangelscript_8h_html_ae4cf50de5273eb8c03c6e91e6e014f0ca2feb963eb04c221e251867bc3a93d79d"><div class="ttname"><a href="angelscript_8h.html#ae4cf50de5273eb8c03c6e91e6e014f0ca2feb963eb04c221e251867bc3a93d79d">asGM_ONLY_IF_EXISTS</a></div><div class="ttdeci">@ asGM_ONLY_IF_EXISTS</div><div class="ttdoc">Don't return any module if it is not found.</div><div class="ttdef"><b>Definition:</b> angelscript.h:524</div></div>
<div class="ttc" id="aangelscript_8h_html_ac8186f029686800b7ce36bde4a55c815"><div class="ttname"><a href="angelscript_8h.html#ac8186f029686800b7ce36bde4a55c815">asUINT</a></div><div class="ttdeci">unsigned int asUINT</div><div class="ttdoc">32 bit unsigned integer</div><div class="ttdef"><b>Definition:</b> angelscript.h:600</div></div>
<div class="ttc" id="aclassas_i_script_module_html"><div class="ttname"><a href="classas_i_script_module.html">asIScriptModule</a></div><div class="ttdoc">The interface to the script modules.</div><div class="ttdef"><b>Definition:</b> angelscript.h:2218</div></div>
<div class="ttc" id="aclassas_i_script_object_html"><div class="ttname"><a href="classas_i_script_object.html">asIScriptObject</a></div><div class="ttdoc">The interface for an instance of a script object.</div><div class="ttdef"><b>Definition:</b> angelscript.h:3413</div></div>
<div class="ttc" id="aclassas_i_script_module_html_a4967db3ed89836ac2f3b529c499d473d"><div class="ttname"><a href="classas_i_script_module.html#a4967db3ed89836ac2f3b529c499d473d">asIScriptModule::GetName</a></div><div class="ttdeci">virtual const char * GetName() const =0</div><div class="ttdoc">Gets the name of the module.</div></div>
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated on Sat Dec 5 2020 23:20:24 for AngelScript by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.18 </li>
</ul>
</div>
</body>
</html>