<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>Issue with calling Lua function from C/C++</title>
		<link>http://www.allegro.cc/forums/view/616476</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Mon, 12 Sep 2016 10:01:38 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Hi,</p><p>for my current Allegro project I want to use Lua as scripting language. But for the moment I have an issue with calling Lua functions in C/C++. It seems that the metatable of an object is overwritten or deprecated when a second object with a different metatable is used in the same script.</p><p>I want to implement a Lua function &#39;update(m,h)&#39; which is called from C/C++ in my project. This function will expect two light userdata objects of different types (this means two different metatables):<br />	m: map object<br />	h: hero object<br />Then I tested three scenarios:</p><p><b>Scenario 1)</b>
</p><div class="source-code snippet"><div class="inner"><pre>function update<span class="k2">(</span>m<span class="k2">)</span>
  print<span class="k2">(</span><span class="s">"[Lua] map-id: "</span>..m:get_id<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span>    <span class="k3">-</span><span class="k3">-</span> <span class="k1">this</span> works
end
</pre></div></div><p>

<b>Scenario 2)</b>
</p><div class="source-code snippet"><div class="inner"><pre>function update<span class="k2">(</span>h<span class="k2">)</span>
  print<span class="k2">(</span><span class="s">"[Lua] hero name: "</span>..h:name<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span>  <span class="k3">-</span><span class="k3">-</span> <span class="k1">this</span> works
end
</pre></div></div><p>

<b>Scenario 3)</b>
</p><div class="source-code snippet"><div class="inner"><pre>function update<span class="k2">(</span>m,h<span class="k2">)</span>
  print<span class="k2">(</span><span class="s">"[Lua] hero name: "</span>..h:name<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span>  <span class="k3">-</span><span class="k3">-</span> <span class="k1">this</span> works
  print<span class="k2">(</span><span class="s">"[Lua] map-id: "</span>..m:get_id<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span>    <span class="k3">-</span><span class="k3">-</span> <span class="k1">this</span> does <span class="k1">not</span> work anymore<span class="k3">!</span> m is available, but get_id<span class="k2">(</span><span class="k2">)</span> cannot be called.
end
</pre></div></div><p>

On C/C++ side, this Lua function is called the following way:
</p><div class="source-code"><div class="toolbar"><span class="button numbers"><b>#</b></span><span class="button select">Select</span><span class="button expand">Expand</span></div><div class="inner"><span class="number">  1</span><span class="k1">void</span> __lua_update<span class="k2">(</span>lua_State<span class="k3">*</span> L,_HERO<span class="k3">*</span> h,MAP<span class="k3">*</span> m<span class="k2">)</span> <span class="k2">{</span>
<span class="number">  2</span>  
<span class="number">  3</span>  lua_getglobal<span class="k2">(</span>L,<span class="s">"update"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  4</span>  
<span class="number">  5</span>  <span class="c">// push map object</span>
<span class="number">  6</span>  lua_pushlightuserdata<span class="k2">(</span>L,<span class="k2">(</span><span class="k1">void</span><span class="k3">*</span><span class="k2">)</span> m<span class="k2">)</span><span class="k2">;</span>
<span class="number">  7</span>  luaL_getmetatable<span class="k2">(</span>L,<span class="s">"L_map"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  8</span>  lua_setmetatable<span class="k2">(</span>L,<span class="k3">-</span><span class="n">2</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  9</span>  
<span class="number"> 10</span>  <span class="c">// push hero object</span>
<span class="number"> 11</span>  lua_pushlightuserdata<span class="k2">(</span>L,<span class="k2">(</span><span class="k1">void</span><span class="k3">*</span><span class="k2">)</span> h<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 12</span>  luaL_getmetatable<span class="k2">(</span>L,<span class="s">"L_hero"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 13</span>  lua_setmetatable<span class="k2">(</span>L,<span class="k3">-</span><span class="n">2</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 14</span>  
<span class="number"> 15</span>  lua_pcall<span class="k2">(</span>L,<span class="n">2</span>,<span class="n">0</span>,<span class="n">0</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 16</span><span class="k2">}</span>
</div></div><p>

NOTE: Both metatables &#39;L_map&#39; and &#39;L_hero&#39; have been created in an earlier init phase.</p><p>Does anybody have some advices how to solve this issue, so that both map and hero object can be accessed within the Lua script?</p><p>Best regards
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kevin Adrian)</author>
		<pubDate>Sun, 11 Sep 2016 02:10:55 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>According to the docs, a table (like the one for update) can only have one metatable. So you&#39;re overwriting the metatable for your update function when you call <span class="source-code">setmetatable<span class="k2">(</span>L , <span class="k3">-</span><span class="n">2</span><span class="k2">)</span></span> twice. Somehow you need to bind the metatable for each object to a separate object.</p><div class="quote_container"><div class="title"><a href="https://www.lua.org/pil/13.html">Programming in LUA : 13</a> said:</div><div class="quote"><p>
Each table in Lua may have its own metatable. (As we will see later, userdata also can have metatables.)
</p></div></div><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Edgar Reynaldo)</author>
		<pubDate>Sun, 11 Sep 2016 02:39:53 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I&#39;m confused by what this <span class="source-code">__lua_update</span> function is supposed to do. It doesn&#39;t seem to make sense to associate a metatable with a table during an &quot;update&quot; function. <img src="http://www.allegro.cc/forums/smileys/undecided.gif" alt=":-/" /> I&#39;ve barely learned the basics of Lua and that was probably 8 years ago, but this C function appears to:</p><ul><li><p>Load the global variable &quot;update&quot; onto the stack (presumably your update function in Lua).
</p></li><li><p>Load a &#39;userdata&#39; object (pointer) to your C object onto the stack.
</p></li><li><p>Load the &quot;L_map&quot; metatable from Lua onto the stack (I&#39;m not sure if that means loading a typed-variable or something more specific).
</p></li><li><p>Associate this userdata object (at -2 index on the stack?) with the metatable on the top of the stack? I&#39;m not sure anymore how this works... It&#39;s been too long. This also pops off the metatable, I think.
</p></li><li><p>Now load the second &#39;userdata&#39; object onto the stack (the first is still there, along with the &quot;update&quot; function).
</p></li><li><p>Associate that userdata object with another metatable and pop the metatable off of the stack.
</p></li><li><p>Finally attempt to call the function with the two userdata objects as arguments.</p></li></ul><p>It sounds vaguely like it should work, assuming that you don&#39;t care about destroying any other &quot;metatable&quot; associated with these objects whenever you call this function... Presumably, if it&#39;s the same one there&#39;s no harm done if Edgar is right about overwriting (as opposed to chaining) them. It also sounds like a very strange pattern. If anything, if you were to do this kind of &quot;hack&quot;, I&#39;d expect you to restore the original metatables before returning...</p><p>So tell me, how far off am I compared to your understanding?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (bamccaig)</author>
		<pubDate>Sun, 11 Sep 2016 09:31:35 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Without looking at the code:
</p><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/616476/1024941#target">Kevin Adrian</a> said:</div><div class="quote"><p>
This function will expect two light userdata objects of different types (this means two different metatables)
</p></div></div><p>
IIRC, <i>light</i> userdata cannot even have individual metatables.</p><div class="quote_container"><div class="title">Lua manual said:</div><div class="quote"><p>
Userdata represent C values in Lua. A light userdata represents a pointer, a void*. It is a value (like a number): you do not create it, it has no individual metatable, and it is not collected (as it was never created). A light userdata is equal to &quot;any&quot; light userdata with the same C address. 
</p></div></div><p>

Maybe it would be better to use a <i>full</i> userdata object for storing your pointers.</p><p>Your code looks fine to me, although I am a bit confused by your update variants.</p><p>Generally, it could be a good idea to keep important Lua values in the registry using luaL_ref and luaL_unref. Pushing them again is quite fast, so you don&#39;t have to recreate the metatables on every update. </p><p>Interfacing Lua can be a pain... A hack that I used once was to use light userdata values as index to a table with weak values. So the C++ pointers were the keys and full userdata with proper metatables set that referenced the same objects were the values. So I could push those by pointer. Not elegant, not very fast, but it worked...
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Polybios)</author>
		<pubDate>Sun, 11 Sep 2016 12:11:50 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Thanks a lot for your advices. I have not that much experience in Lua and binding to C/C++.</p><p>I will check my code and rework it.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kevin Adrian)</author>
		<pubDate>Mon, 12 Sep 2016 10:01:38 +0000</pubDate>
	</item>
</rss>
