207 lines
17 KiB
HTML
207 lines
17 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" lang="en-US">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
|
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
|
|
<meta name="generator" content="Doxygen 1.9.6"/>
|
|
<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:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
|
|
$(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 id="projectrow">
|
|
<td id="projectlogo"><img alt="Logo" src="aslogo_small.png"/></td>
|
|
<td id="projectalign">
|
|
<div id="projectname">AngelScript
|
|
</div>
|
|
</td>
|
|
<td> <div id="MSearchBox" class="MSearchBoxInactive">
|
|
<span class="left">
|
|
<span id="MSearchSelect" onmouseover="return searchBox.OnSearchSelectShow()" onmouseout="return searchBox.OnSearchSelectHide()"> </span>
|
|
<input type="text" id="MSearchField" value="" placeholder="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.svg" alt=""/></a>
|
|
</span>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<!-- end header part -->
|
|
<!-- Generated by Doxygen 1.9.6 -->
|
|
<script type="text/javascript">
|
|
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
|
|
var searchBox = new SearchBox("searchBox", "search/",'.html');
|
|
/* @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:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
|
|
$(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">
|
|
<div id="MSearchResults">
|
|
<div class="SRPage">
|
|
<div id="SRIndex">
|
|
<div id="SRResults"></div>
|
|
<div class="SRStatus" id="Loading">Loading...</div>
|
|
<div class="SRStatus" id="Searching">Searching...</div>
|
|
<div class="SRStatus" id="NoMatches">No Matches</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div><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->RegisterFuncdef(<span class="stringliteral">"void CallbackFunc()"</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->RegisterGlobalFunction(<span class="stringliteral">"void SetCallback(CallbackFunc @cb)"</span>, <a class="code hl_define" href="angelscript_8h.html#a78f8f2c7f1c88b12e74a5ac47b4184ae">asFUNCTION</a>(SetCallback), <a class="code hl_enumvalue" href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4a68ae43cc91cdfc3fa4590c9e6164e4f4">asCALL_CDECL</a>); </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:230</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:685</div></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);
|
|
}
|
|
|
|
// 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't forget to release this before cleaning up the engine.</span></div>
|
|
<div class="line"><a class="code hl_class" 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 hl_class" 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-><a class="code hl_function" 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't be used any more</span></div>
|
|
<div class="line">}</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:4000</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><!-- 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 hl_class" 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 hl_class" 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 hl_class" 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-><a class="code hl_function" href="classas_i_script_function.html#a0a98f1f7f91574a11d7d8c5062bdcdee">Release</a>();</div>
|
|
<div class="line"> <span class="keywordflow">if</span>( callbackObject )</div>
|
|
<div class="line"> engine->ReleaseScriptObject(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 && cb-><a class="code hl_function" href="classas_i_script_function.html#aa4d06c7d590e7eb4df280a8224f4499c">GetFuncType</a>() == <a class="code hl_enumvalue" href="angelscript_8h.html#a06fb2a1ebf5d007e0d542abced1b648fa02773b148f9c6fb3ed5d945a940f302a">asFUNC_DELEGATE</a> )</div>
|
|
<div class="line"> {</div>
|
|
<div class="line"> callbackObject = cb-><a class="code hl_function" href="classas_i_script_function.html#a16788f4e72c33974964b90d920b78a58">GetDelegateObject</a>();</div>
|
|
<div class="line"> callbackObjectType = cb-><a class="code hl_function" href="classas_i_script_function.html#af409c42ce46f7cc6ade36631cee01209">GetDelegateObjectType</a>();</div>
|
|
<div class="line"> callback = cb-><a class="code hl_function" href="classas_i_script_function.html#a34ac063e9e6c05dde8073d7637142573">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->AddRefScriptObject(callbackObject, callbackObjectType);</div>
|
|
<div class="line"> callback-><a class="code hl_function" 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't be used anymore</span></div>
|
|
<div class="line"> cb-><a class="code hl_function" 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't be used any more</span></div>
|
|
<div class="line"> }</div>
|
|
<div class="line">}</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:563</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_a16788f4e72c33974964b90d920b78a58"><div class="ttname"><a href="classas_i_script_function.html#a16788f4e72c33974964b90d920b78a58">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_a34ac063e9e6c05dde8073d7637142573"><div class="ttname"><a href="classas_i_script_function.html#a34ac063e9e6c05dde8073d7637142573">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_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>
|
|
<div class="ttc" id="aclassas_i_script_function_html_af409c42ce46f7cc6ade36631cee01209"><div class="ttname"><a href="classas_i_script_function.html#af409c42ce46f7cc6ade36631cee01209">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_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:3704</div></div>
|
|
</div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>Although delegates use the <a class="el" href="classas_i_script_function.html" title="The interface for a script function description.">asIScriptFunction</a> interface, they are not actual functions. Because of this they are not owned by anymodule, i.e. <a class="el" href="classas_i_script_function.html#af984c26f8515e016065feb6db17aea69">GetModule</a> will always return null. Likewise they do not have a specific function id, i.e. <a class="el" href="classas_i_script_function.html#a7aca255486dd77b8846f545495128cac">GetId</a> will return 0. </dd></dl>
|
|
</div></div><!-- contents -->
|
|
</div><!-- PageDoc -->
|
|
</div><!-- doc-content -->
|
|
<!-- start footer part -->
|
|
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
|
<ul>
|
|
<li class="footer">Generated on Sun May 21 2023 10:12:40 for AngelScript by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.6 </li>
|
|
</ul>
|
|
</div>
|
|
</body>
|
|
</html>
|