|
@@ -81,11 +81,11 @@
|
|
|
|
|
|
|
|
<ul>
|
|
<ul>
|
|
|
|
|
|
|
|
- <li class="toctree-l3"><a href="#general">General</a></li>
|
|
|
|
|
|
|
+ <li class="toctree-l3"><a href="#wrapping">Wrapping</a></li>
|
|
|
|
|
|
|
|
<li><a class="toctree-l4" href="#functions">Functions</a></li>
|
|
<li><a class="toctree-l4" href="#functions">Functions</a></li>
|
|
|
|
|
|
|
|
- <li><a class="toctree-l4" href="#methods-and-fields">Methods and fields</a></li>
|
|
|
|
|
|
|
+ <li><a class="toctree-l4" href="#class-members">Class members</a></li>
|
|
|
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</ul>
|
|
@@ -136,42 +136,62 @@
|
|
|
<div role="main">
|
|
<div role="main">
|
|
|
<div class="section">
|
|
<div class="section">
|
|
|
|
|
|
|
|
- <h1 id="general">General</h1>
|
|
|
|
|
-<p>Luwra provides a simple way to generate
|
|
|
|
|
-Lua <a href="http://www.lua.org/manual/5.3/manual.html#lua_CFunction">C functions</a> from functions and class
|
|
|
|
|
|
|
+ <h1 id="wrapping">Wrapping</h1>
|
|
|
|
|
+<p>Luwra provides a simple way to generate Lua <a href="http://www.lua.org/manual/5.3/manual.html#lua_CFunction">C functions</a> from functions and class
|
|
|
members like methods and accessors using the <code>LUWRA_WRAP</code> macro. These kind of C functions are
|
|
members like methods and accessors using the <code>LUWRA_WRAP</code> macro. These kind of C functions are
|
|
|
-useful, because they work just like regular Lua functions within the Lua virtual machine.</p>
|
|
|
|
|
|
|
+useful, because they work just like regular Lua functions within the Lua virtual machine.
|
|
|
|
|
+Registering these functions is the most straightforward way of providing the functionality of your
|
|
|
|
|
+application to Lua.</p>
|
|
|
<h2 id="functions">Functions</h2>
|
|
<h2 id="functions">Functions</h2>
|
|
|
-<p>When wrapping functions, one must consider that all parameter types must be able to be read from the
|
|
|
|
|
-stack and the return type must be able to be pushed onto the stack.</p>
|
|
|
|
|
-<p>Assuming you have a function similiar to this:</p>
|
|
|
|
|
|
|
+<p>When wrapping functions, one must consider that all parameter types must be read from the
|
|
|
|
|
+stack and the return type must be pushed onto the stack.</p>
|
|
|
|
|
+<h3 id="example">Example</h3>
|
|
|
|
|
+<p>Lets assume you want to make the following function available in Lua.</p>
|
|
|
<pre><code class="c++">int my_function(const char* a, int b) {
|
|
<pre><code class="c++">int my_function(const char* a, int b) {
|
|
|
return /* magic */;
|
|
return /* magic */;
|
|
|
}
|
|
}
|
|
|
</code></pre>
|
|
</code></pre>
|
|
|
|
|
|
|
|
-<p>You can easily wrap it using the <code>LUWRA_WRAP</code> macro:</p>
|
|
|
|
|
-<pre><code class="c++">// Convert to lua_CFunction
|
|
|
|
|
-lua_CFunction cfun = LUWRA_WRAP(my_function);
|
|
|
|
|
-
|
|
|
|
|
-// Do something with it, for example set it as a Lua global function
|
|
|
|
|
-luwra::setGlobal(lua, "my_function", cfun);
|
|
|
|
|
|
|
+<p>First, you must generate a Lua <a href="http://www.lua.org/manual/5.3/manual.html#lua_CFunction">C function</a>. One utilizes the <code>LUWRA_WRAP</code> macro for
|
|
|
|
|
+this.</p>
|
|
|
|
|
+<pre><code class="c++">lua_CFunction cfun = LUWRA_WRAP(my_function);
|
|
|
</code></pre>
|
|
</code></pre>
|
|
|
|
|
|
|
|
<p><strong>Note:</strong> Do not provide the address of your function (e.g. <code>&my_function</code>) to any wrapping macro.
|
|
<p><strong>Note:</strong> Do not provide the address of your function (e.g. <code>&my_function</code>) to any wrapping macro.
|
|
|
-The macros will take care of this themselves. You must provide only the name of the function.</p>
|
|
|
|
|
-<p>Calling the function from Lua is fairly straightforward:</p>
|
|
|
|
|
-<pre><code class="lua">local my_result = my_function("Hello World", 1337)
|
|
|
|
|
-print(my_result)
|
|
|
|
|
|
|
+The macro will take care of this itself. You must provide only the name of the function.</p>
|
|
|
|
|
+<p>Once you have the C function, you can register it in the global namespace.</p>
|
|
|
|
|
+<pre><code class="c++">luwra::setGlobal(lua, "my_function", cfun);
|
|
|
|
|
+</code></pre>
|
|
|
|
|
+
|
|
|
|
|
+<p>Invoking the function in Lua is fairly straightforward.</p>
|
|
|
|
|
+<pre><code class="lua">print(my_function("Hello World", 1337))
|
|
|
|
|
+</code></pre>
|
|
|
|
|
+
|
|
|
|
|
+<h3 id="performance">Performance</h3>
|
|
|
|
|
+<p><a href="http://www.lua.org/manual/5.3/manual.html#lua_CFunction">C functions</a> are dynamically created at compile-time. All of the functions involved
|
|
|
|
|
+in wrapping are marked as <code>inline</code>, which means modern compilers produce wrapper functions with zero
|
|
|
|
|
+overhead, when optimization is turned on.</p>
|
|
|
|
|
+<p>For the example above, the resulting code would look similiar to the following.</p>
|
|
|
|
|
+<pre><code class="c++">static int cfun(lua_State* state) {
|
|
|
|
|
+ lua_pushinteger(
|
|
|
|
|
+ state,
|
|
|
|
|
+ my_function(
|
|
|
|
|
+ luaL_checkstring(state, 1),
|
|
|
|
|
+ luaL_checkinteger(state, 1)
|
|
|
|
|
+ )
|
|
|
|
|
+ );
|
|
|
|
|
+ return 1;
|
|
|
|
|
+}
|
|
|
</code></pre>
|
|
</code></pre>
|
|
|
|
|
|
|
|
-<h2 id="methods-and-fields">Methods and fields</h2>
|
|
|
|
|
-<p>It is also possible to turn C++ field accessors and methods into <code>lua_CFunction</code>s. It is a little
|
|
|
|
|
-trickier than wrapping normal functions. The resulting Lua functions expect the first (or <code>self</code>)
|
|
|
|
|
-parameter to be a user type instance of the type which the wrapped field or method belongs to.</p>
|
|
|
|
|
|
|
+<h2 id="class-members">Class members</h2>
|
|
|
|
|
+<p>Although a little trickier, it is also possible to turn C++ field accessors and methods into Lua
|
|
|
|
|
+<a href="http://www.lua.org/manual/5.3/manual.html#lua_CFunction">C functions</a>. The resulting Lua functions expect the first (or <code>self</code>) parameter to
|
|
|
|
|
+be an instance of the type which the wrapped field or method belongs to.</p>
|
|
|
<p><strong>Note:</strong> Before you wrap fields and methods manually, you might want to take a look at the
|
|
<p><strong>Note:</strong> Before you wrap fields and methods manually, you might want to take a look at the
|
|
|
<a href="../user-types/">User Types</a> section.</p>
|
|
<a href="../user-types/">User Types</a> section.</p>
|
|
|
-<p>The next examples will operate on the following structure:</p>
|
|
|
|
|
|
|
+<h3 id="example_1">Example</h3>
|
|
|
|
|
+<p>This example will operate on the following structure.</p>
|
|
|
<pre><code class="c++">struct Point {
|
|
<pre><code class="c++">struct Point {
|
|
|
double x, y;
|
|
double x, y;
|
|
|
|
|
|
|
@@ -184,19 +204,20 @@ parameter to be a user type instance of the type which the wrapped field or meth
|
|
|
};
|
|
};
|
|
|
</code></pre>
|
|
</code></pre>
|
|
|
|
|
|
|
|
-<p>In order to wrap <code>x</code>, <code>y</code> and <code>scale</code> we utilize the <code>LUWRA_WRAP</code> macro again:</p>
|
|
|
|
|
|
|
+<p>Wrapping field accessors and methods works identical to wrapping functions.</p>
|
|
|
<pre><code class="c++">lua_CFunction cfun_x = LUWRA_WRAP(Point::x),
|
|
<pre><code class="c++">lua_CFunction cfun_x = LUWRA_WRAP(Point::x),
|
|
|
cfun_y = LUWRA_WRAP(Point::y),
|
|
cfun_y = LUWRA_WRAP(Point::y),
|
|
|
cfun_scale = LUWRA_WRAP(Point::scale);
|
|
cfun_scale = LUWRA_WRAP(Point::scale);
|
|
|
|
|
|
|
|
-// Register as globals
|
|
|
|
|
|
|
+// Register in global namespace
|
|
|
luwra::setGlobal(lua, "x", cfun_x);
|
|
luwra::setGlobal(lua, "x", cfun_x);
|
|
|
luwra::setGlobal(lua, "y", cfun_y);
|
|
luwra::setGlobal(lua, "y", cfun_y);
|
|
|
luwra::setGlobal(lua, "scale", cfun_scale);
|
|
luwra::setGlobal(lua, "scale", cfun_scale);
|
|
|
</code></pre>
|
|
</code></pre>
|
|
|
|
|
|
|
|
-<p>Usage looks like this:</p>
|
|
|
|
|
-<pre><code class="lua">local my_point = -- Magic
|
|
|
|
|
|
|
+<p>Usage in Lua is analogous to function usage.</p>
|
|
|
|
|
+<pre><code class="lua">-- Instantiate 'Point' here, have a look at the User Types section to find out how to do this
|
|
|
|
|
+local my_point = ...
|
|
|
|
|
|
|
|
-- Access 'x' and 'y' field
|
|
-- Access 'x' and 'y' field
|
|
|
print(x(my_point), y(my_point))
|
|
print(x(my_point), y(my_point))
|