{"id":1208,"date":"2013-09-05T01:00:00","date_gmt":"2013-09-04T23:00:00","guid":{"rendered":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1208"},"modified":"2013-09-04T15:48:19","modified_gmt":"2013-09-04T14:48:19","slug":"lua-and-c","status":"publish","type":"post","link":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1208","title":{"rendered":"Lua and C++"},"content":{"rendered":"<p>I\u00e2\u20ac\u2122ve not yet had a project that\u00e2\u20ac\u2122s needed an embedded scripting language. When I do, I think I\u00e2\u20ac\u2122ll reach for <a href=\"http:\/\/www.lua.org\/\">Lua<\/a>.<\/p>\n<pre><code>$ apt-get install lua5.2 liblua5.2-dev<\/code><\/pre>\n<p>Command line lua:<\/p>\n<pre><code>$ lua\nLua 5.2.2  Copyright (C) 1994-2013 Lua.org, PUC-Rio\n&gt; print(&quot;Hello, World&quot;) \nHello, World<\/code><\/pre>\n<p>Embedded lua:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\"><span class=\"ot\">#include &lt;lua5.2\/lua.hpp&gt;<\/span>\n\n<span class=\"dt\">int<\/span> main()\n{\n    <span class=\"co\">\/\/ Create a Lua virtual machine<\/span>\n    lua_State *l = luaL_newstate();\n\n    <span class=\"co\">\/\/ Make all the lua libs to the virtual machine<\/span>\n    luaL_openlibs(l);\n\n    <span class=\"co\">\/\/ Test it<\/span>\n    luaL_dostring(l, <span class=\"st\">&quot;print(<\/span><span class=\"ch\">\\&quot;<\/span><span class=\"st\">Helua, World!<\/span><span class=\"ch\">\\&quot;<\/span><span class=\"st\">)&quot;<\/span>);\n    cout &lt;&lt; lua_tostring(l, -<span class=\"dv\">1<\/span>);\n\n    lua_close(l);\n}<\/code><\/pre>\n<p>I\u00e2\u20ac\u2122m not sure it gets much easier.<\/p>\n<h2 id=\"calling-c-from-lua\">Calling C from Lua<\/h2>\n<p>Obviously the main reason for embedding a scripting language is to make custom routines from your application available to the script.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\"><span class=\"dt\">int<\/span> x = <span class=\"dv\">0<\/span>;\n\n<span class=\"dt\">int<\/span> customFunction(lua_State *L) {\n    <span class=\"co\">\/\/ Number of elements on the parameter stack<\/span>\n    <span class=\"dt\">int<\/span> n = lua_gettop(L);\n    <span class=\"kw\">if<\/span>( n == <span class=\"dv\">0<\/span> )\n        <span class=\"kw\">return<\/span> <span class=\"dv\">0<\/span>;\n\n    <span class=\"kw\">for<\/span>(<span class=\"dt\">int<\/span> i = <span class=\"dv\">0<\/span>; i &lt; n; i++) {\n        <span class=\"kw\">if<\/span>( !lua_isnumber(L, i<span class=\"dv\">+1<\/span>) ) {\n            lua_pushstring(L, <span class=\"st\">&quot;incorrect arguments&quot;<\/span>);\n            lua_error(L);\n        }\n        x += lua_tointeger(L, i<span class=\"dv\">+1<\/span>);\n    }\n\n    <span class=\"co\">\/\/ return x<\/span>\n    lua_pushinteger(L, x);\n    <span class=\"kw\">return<\/span> <span class=\"dv\">1<\/span>;\n}<\/code><\/pre>\n<p>Then register it and call it.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\"><span class=\"dt\">int<\/span> main()\n{\n    <span class=\"co\">\/\/ Create a Lua virtual machine<\/span>\n    lua_State *l = luaL_newstate();\n\n    lua_register(l, <span class=\"st\">&quot;customFunction&quot;<\/span>, customFunction);\n\n    <span class=\"co\">\/\/ Test it<\/span>\n    luaL_dostring(l, <span class=\"st\">&quot;return customFunction(1)&quot;<\/span>);\n    std::cout &lt;&lt; lua_tointeger(l, -<span class=\"dv\">1<\/span>) &lt;&lt; endl;\n\n    lua_close(l);\n}<\/code><\/pre>\n<p>It took me quite a while to realise that \u00e2\u20ac\u0153<code>return<\/code>\u00e2\u20ac\u009d was needed inside the <code>luaL_dostring()<\/code> parameter. It seems that the string being evaluated is treated as being inside some anonymous function and we are effectively calling that entire function. Now I understand that, the following from the Lua reference manual is clearer:<\/p>\n<blockquote>\n<p><code>int luaL_dofile (lua_State *L, const char *filename);<\/code><\/p>\n<p>Loads and runs the given file. It is defined as the following macro:<\/p>\n<pre><code> (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))<\/code><\/pre>\n<p>It returns false if there are no errors or true in case of errors.<\/p>\n<\/blockquote>\n<p><code>luaL_loadfile()<\/code> uses <code>lua_load()<\/code> which says this:<\/p>\n<blockquote>\n<p>Loads a Lua chunk (without running it). If there are no errors, lua_load pushes the compiled chunk as a Lua function on top of the stack.<\/p>\n<\/blockquote>\n<p>So the string we give to <code>luaL_dostring()<\/code> becomes a function on the stack, which is what <code>lua_pcall()<\/code> calls \u00e2\u20ac\u00a6 <em>calls<\/em> means it must return. That\u00e2\u20ac\u2122s in addition to our <code>customFunction()<\/code> which itself returns to this anonymous function.<\/p>\n<h2 id=\"calling-lua-from-c\">Calling Lua from C<\/h2>\n<p>The reverse will also be useful; when you want to let your script react to events generated by the C\/C++ application.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\"><span class=\"dt\">int<\/span> main()\n{\n    <span class=\"co\">\/\/ Create a Lua virtual machine<\/span>\n    lua_State *l = luaL_newstate();\n\n    <span class=\"co\">\/\/ Define the lua callback in the state; note that this doesn&#39;t<\/span>\n    <span class=\"co\">\/\/ call the function, it creates the reference to it in the<\/span>\n    <span class=\"co\">\/\/ global table<\/span>\n    luaL_dostring(L, R<span class=\"st\">&quot;***(<\/span>\n        function onEvent(a)\n            <span class=\"kw\">return<\/span> a<span class=\"dv\">+10<\/span>\n        end\n    )***<span class=\"st\">&quot;));<\/span>\n\n    <span class=\"co\">\/\/ Random number<\/span>\n    <span class=\"dt\">int<\/span> x = <span class=\"bn\">0x7673f562<\/span>;\n\n    <span class=\"co\">\/\/ What function do we want to call?  Find it and push it onto<\/span>\n    <span class=\"co\">\/\/ the stack<\/span>\n    lua_getglobal(L, <span class=\"st\">&quot;onEvent&quot;<\/span>);\n    <span class=\"co\">\/\/ Then push the arguments<\/span>\n    lua_pushnumber(L, x);\n    <span class=\"co\">\/\/ Call it, telling Lua it has one argument, one result<\/span>\n    lua_call(L, <span class=\"dv\">1<\/span>, <span class=\"dv\">1<\/span>);\n    <span class=\"co\">\/\/ Fetch the result<\/span>\n    <span class=\"dt\">int<\/span> y = lua_tointeger(L, -<span class=\"dv\">1<\/span>);\n    <span class=\"co\">\/\/ Restore the stack<\/span>\n    lua_pop(L, <span class=\"dv\">1<\/span>);\n\n    cout &lt;&lt; <span class=\"st\">&quot;LUA.onEvent()&quot;<\/span> = y &lt;&lt; endl;\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I\u00e2\u20ac\u2122ve not yet had a project that\u00e2\u20ac\u2122s needed an embedded scripting language. When I do, I think I\u00e2\u20ac\u2122ll reach for Lua. $ apt-get install lua5.2 liblua5.2-dev Command line lua: $ lua Lua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio &gt; print(&quot;Hello, World&quot;) Hello, World Embedded lua: #include &lt;lua5.2\/lua.hpp&gt; int main() { \/\/ Create a Lua virtual\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.fussylogic.co.uk\/blog\/?p=1208\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[66,109,6],"_links":{"self":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1208"}],"collection":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1208"}],"version-history":[{"count":3,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1208\/revisions"}],"predecessor-version":[{"id":1211,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1208\/revisions\/1211"}],"wp:attachment":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1208"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1208"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1208"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}