Angelscript/docs/manual/doc_callbacks.html

208 lines
18 KiB
HTML

<!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: Funcdefs and script callback functions</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_callbacks.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">Funcdefs and script callback functions </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><a class="el" href="doc_global_funcdef.html">Funcdefs</a> are used to define a function signature for callbacks. This funcdef is then used to declare variables or function parameters that can hold handles to functions of matching signature.</p>
<p>The application can also <a class="el" href="classas_i_script_engine.html#a03c1a2cc23ae4b742c927f3472a1a4f7">register funcdefs</a> as part of the application interface if the intention is for the script to set callbacks that will be called from the application. Once this is done, the application can receive the function handles as an <a class="el" href="classas_i_script_function.html" title="The interface for a script function description.">asIScriptFunction</a> pointer which can then be <a class="el" href="doc_call_script_func.html">executed</a> normally.</p>
<h1><a class="anchor" id="doc_callbacks_example"></a>
An example</h1>
<p>Let's say the application needs to allow the script to set a callback that will then be called at some event. To do this the application would first register the funcdef that defines the signature of the callback. Then it needs to register the function that will be used to set the callback from the script.</p>
<div class="fragment"><div class="line"><span class="comment">// Register a simple funcdef for the callback</span></div>
<div class="line">engine-&gt;<a class="code" href="classas_i_script_engine.html#a03c1a2cc23ae4b742c927f3472a1a4f7">RegisterFuncdef</a>(<span class="stringliteral">&quot;void CallbackFunc()&quot;</span>); </div>
<div class="line"> </div>
<div class="line"><span class="comment">// Register a function for setting the callback</span></div>
<div class="line">engine-&gt;<a class="code" href="classas_i_script_engine.html#a2f84b9b51733f22c68b8448b02c2f1c7">RegisterGlobalFunction</a>(<span class="stringliteral">&quot;void SetCallback(CallbackFunc @cb)&quot;</span>, <a class="code" href="angelscript_8h.html#a78f8f2c7f1c88b12e74a5ac47b4184ae">asFUNCTION</a>(SetCallback), <a class="code" href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4a68ae43cc91cdfc3fa4590c9e6164e4f4">asCALL_CDECL</a>); </div>
</div><!-- fragment --><p>With this interface, the script would be able to inform the callback like this:</p>
<pre>
void main()
{
// Tell the application what script function to call
SetCallback(MyCallback);
}</pre><pre> // The signature matches the registered CallbackFunc funcdef
void MyCallback()
{
...
}
</pre><p>The implementation for the SetCallback function might look something like this.</p>
<div class="fragment"><div class="line"><span class="comment">// The callback is a script function.</span></div>
<div class="line"><span class="comment">// Don&#39;t forget to release this before cleaning up the engine.</span></div>
<div class="line"><a class="code" href="classas_i_script_function.html">asIScriptFunction</a> *callback = 0;</div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">void</span> SetCallback(<a class="code" href="classas_i_script_function.html">asIScriptFunction</a> *cb)</div>
<div class="line">{</div>
<div class="line"> <span class="comment">// Release the previous callback, if any</span></div>
<div class="line"> <span class="keywordflow">if</span>( callback )</div>
<div class="line"> callback-&gt;<a class="code" href="classas_i_script_function.html#a0a98f1f7f91574a11d7d8c5062bdcdee">Release</a>();</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Store the received handle for later use</span></div>
<div class="line"> callback = cb;</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Do not release the received script function </span></div>
<div class="line"> <span class="comment">// until it won&#39;t be used any more</span></div>
<div class="line">}</div>
</div><!-- fragment --><p>To call the actual callback when it is time, the application uses the script context just like for any other <a class="el" href="doc_call_script_func.html">call to a script function</a>.</p>
<h1><a class="anchor" id="doc_callbacks_delegate"></a>
Delegates</h1>
<p>Of course, callbacks can be used with <a class="el" href="doc_datatypes_funcptr.html">delegates</a> as well. Delegates are special function objects that holds a reference to an object and the method it should call on it. If this is exactly how the application should treat them, then the above example will work exactly the same and the application never needs to worry about whether the callback is actually a global function or a delegate object.</p>
<p>Sometimes however, it may be beneficial to break up the delegate, and have the application store the actual object and method separately, for example if the application should use a <a class="el" href="doc_adv_weakref.html">weak reference</a> to avoid keeping the object alive longer than desired. The following shows how to retrieve the internals of the delegate:</p>
<div class="fragment"><div class="line"><span class="comment">// The callback, and accompanying object, if the callback is a class method</span></div>
<div class="line"><a class="code" href="classas_i_script_function.html">asIScriptFunction</a> *callback = 0;</div>
<div class="line"><span class="keywordtype">void</span> *callbackObject = 0;</div>
<div class="line"><a class="code" href="classas_i_type_info.html">asITypeInfo</a> *callbackObjectType = 0;</div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">void</span> SetCallback(<a class="code" href="classas_i_script_function.html">asIScriptFunction</a> *cb)</div>
<div class="line">{</div>
<div class="line"> <span class="comment">// Release the previous callback, if any</span></div>
<div class="line"> <span class="keywordflow">if</span>( callback )</div>
<div class="line"> callback-&gt;<a class="code" href="classas_i_script_function.html#a0a98f1f7f91574a11d7d8c5062bdcdee">Release</a>();</div>
<div class="line"> <span class="keywordflow">if</span>( callbackObject )</div>
<div class="line"> engine-&gt;<a class="code" href="classas_i_script_engine.html#a82873d3769ded547894a7c3d52c220fd">ReleaseScriptObject</a>(callbackObject, callbackObjectType);</div>
<div class="line"> callback = 0;</div>
<div class="line"> callbackObject = 0;</div>
<div class="line"> callbackObjectType = 0;</div>
<div class="line"> </div>
<div class="line"> <span class="keywordflow">if</span>( cb &amp;&amp; cb-&gt;<a class="code" href="classas_i_script_function.html#aa4d06c7d590e7eb4df280a8224f4499c">GetFuncType</a>() == <a class="code" href="angelscript_8h.html#a06fb2a1ebf5d007e0d542abced1b648fa02773b148f9c6fb3ed5d945a940f302a">asFUNC_DELEGATE</a> )</div>
<div class="line"> {</div>
<div class="line"> callbackObject = cb-&gt;<a class="code" href="classas_i_script_function.html#ae1786c3f4341dc3bfcaacc3cb8900a57">GetDelegateObject</a>();</div>
<div class="line"> callbackObjectType = cb-&gt;<a class="code" href="classas_i_script_function.html#ad79461f80fcffd513b43564d75cc5360">GetDelegateObjectType</a>();</div>
<div class="line"> callback = cb-&gt;<a class="code" href="classas_i_script_function.html#aa28f4e68da8abb770d7f725375bcd2bb">GetDelegateFunction</a>();</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Hold on to the object and method</span></div>
<div class="line"> engine-&gt;<a class="code" href="classas_i_script_engine.html#ade1d309876c876c733d437a53e708c28">AddRefScriptObject</a>(callbackObject, callbackObjectType);</div>
<div class="line"> callback-&gt;<a class="code" href="classas_i_script_function.html#a0a00f9581e7ece5f2a536d0e22c10d0c">AddRef</a>();</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Release the delegate, since it won&#39;t be used anymore</span></div>
<div class="line"> cb-&gt;<a class="code" href="classas_i_script_function.html#a0a98f1f7f91574a11d7d8c5062bdcdee">Release</a>();</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">else</span></div>
<div class="line"> {</div>
<div class="line"> <span class="comment">// Store the received handle for later use</span></div>
<div class="line"> callback = cb;</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Do not release the received script function </span></div>
<div class="line"> <span class="comment">// until it won&#39;t be used any more</span></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_a82873d3769ded547894a7c3d52c220fd"><div class="ttname"><a href="classas_i_script_engine.html#a82873d3769ded547894a7c3d52c220fd">asIScriptEngine::ReleaseScriptObject</a></div><div class="ttdeci">virtual void ReleaseScriptObject(void *obj, const asITypeInfo *type)=0</div><div class="ttdoc">Release the object pointer.</div></div>
<div class="ttc" id="aclassas_i_script_function_html_a0a00f9581e7ece5f2a536d0e22c10d0c"><div class="ttname"><a href="classas_i_script_function.html#a0a00f9581e7ece5f2a536d0e22c10d0c">asIScriptFunction::AddRef</a></div><div class="ttdeci">virtual int AddRef() const =0</div><div class="ttdoc">Increases the reference counter.</div></div>
<div class="ttc" id="aclassas_i_script_function_html_a0a98f1f7f91574a11d7d8c5062bdcdee"><div class="ttname"><a href="classas_i_script_function.html#a0a98f1f7f91574a11d7d8c5062bdcdee">asIScriptFunction::Release</a></div><div class="ttdeci">virtual int Release() const =0</div><div class="ttdoc">Decrease reference counter.</div></div>
<div class="ttc" id="aclassas_i_script_engine_html_a03c1a2cc23ae4b742c927f3472a1a4f7"><div class="ttname"><a href="classas_i_script_engine.html#a03c1a2cc23ae4b742c927f3472a1a4f7">asIScriptEngine::RegisterFuncdef</a></div><div class="ttdeci">virtual int RegisterFuncdef(const char *decl)=0</div><div class="ttdoc">Registers a function definition.</div></div>
<div class="ttc" id="aclassas_i_script_function_html_ad79461f80fcffd513b43564d75cc5360"><div class="ttname"><a href="classas_i_script_function.html#ad79461f80fcffd513b43564d75cc5360">asIScriptFunction::GetDelegateObjectType</a></div><div class="ttdeci">virtual asITypeInfo * GetDelegateObjectType() const =0</div><div class="ttdoc">Returns the type of the delegated object.</div></div>
<div class="ttc" id="aclassas_i_script_engine_html_a2f84b9b51733f22c68b8448b02c2f1c7"><div class="ttname"><a href="classas_i_script_engine.html#a2f84b9b51733f22c68b8448b02c2f1c7">asIScriptEngine::RegisterGlobalFunction</a></div><div class="ttdeci">virtual int RegisterGlobalFunction(const char *declaration, const asSFuncPtr &amp;funcPointer, asDWORD callConv, void *auxiliary=0)=0</div><div class="ttdoc">Registers a global function.</div></div>
<div class="ttc" id="aangelscript_8h_html_a78f8f2c7f1c88b12e74a5ac47b4184ae"><div class="ttname"><a href="angelscript_8h.html#a78f8f2c7f1c88b12e74a5ac47b4184ae">asFUNCTION</a></div><div class="ttdeci">#define asFUNCTION(f)</div><div class="ttdoc">Returns an asSFuncPtr representing the function specified by the name.</div><div class="ttdef"><b>Definition:</b> angelscript.h:675</div></div>
<div class="ttc" id="aclassas_i_script_function_html_aa28f4e68da8abb770d7f725375bcd2bb"><div class="ttname"><a href="classas_i_script_function.html#aa28f4e68da8abb770d7f725375bcd2bb">asIScriptFunction::GetDelegateFunction</a></div><div class="ttdeci">virtual asIScriptFunction * GetDelegateFunction() const =0</div><div class="ttdoc">Returns the function for the delegate.</div></div>
<div class="ttc" id="aclassas_i_type_info_html"><div class="ttname"><a href="classas_i_type_info.html">asITypeInfo</a></div><div class="ttdoc">The interface for describing types This interface is used to describe the types in the script engine.</div><div class="ttdef"><b>Definition:</b> angelscript.h:3527</div></div>
<div class="ttc" id="aclassas_i_script_function_html_ae1786c3f4341dc3bfcaacc3cb8900a57"><div class="ttname"><a href="classas_i_script_function.html#ae1786c3f4341dc3bfcaacc3cb8900a57">asIScriptFunction::GetDelegateObject</a></div><div class="ttdeci">virtual void * GetDelegateObject() const =0</div><div class="ttdoc">Returns the object for the delegate.</div></div>
<div class="ttc" id="aclassas_i_script_function_html"><div class="ttname"><a href="classas_i_script_function.html">asIScriptFunction</a></div><div class="ttdoc">The interface for a script function description.</div><div class="ttdef"><b>Definition:</b> angelscript.h:3823</div></div>
<div class="ttc" id="aclassas_i_script_engine_html_ade1d309876c876c733d437a53e708c28"><div class="ttname"><a href="classas_i_script_engine.html#ade1d309876c876c733d437a53e708c28">asIScriptEngine::AddRefScriptObject</a></div><div class="ttdeci">virtual void AddRefScriptObject(void *obj, const asITypeInfo *type)=0</div><div class="ttdoc">Increase the reference counter for the script object.</div></div>
<div class="ttc" id="aangelscript_8h_html_a3ec92ea3c4762e44c2df788ceccdd1e4a68ae43cc91cdfc3fa4590c9e6164e4f4"><div class="ttname"><a href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4a68ae43cc91cdfc3fa4590c9e6164e4f4">asCALL_CDECL</a></div><div class="ttdeci">@ asCALL_CDECL</div><div class="ttdoc">A cdecl function.</div><div class="ttdef"><b>Definition:</b> angelscript.h:226</div></div>
<div class="ttc" id="aangelscript_8h_html_a06fb2a1ebf5d007e0d542abced1b648fa02773b148f9c6fb3ed5d945a940f302a"><div class="ttname"><a href="angelscript_8h.html#a06fb2a1ebf5d007e0d542abced1b648fa02773b148f9c6fb3ed5d945a940f302a">asFUNC_DELEGATE</a></div><div class="ttdeci">@ asFUNC_DELEGATE</div><div class="ttdoc">A function delegate.</div><div class="ttdef"><b>Definition:</b> angelscript.h:557</div></div>
<div class="ttc" id="aclassas_i_script_function_html_aa4d06c7d590e7eb4df280a8224f4499c"><div class="ttname"><a href="classas_i_script_function.html#aa4d06c7d590e7eb4df280a8224f4499c">asIScriptFunction::GetFuncType</a></div><div class="ttdeci">virtual asEFuncType GetFuncType() const =0</div><div class="ttdoc">Returns the type of the function.</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>