__call and metatables

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

__call and metatables

Remo Dentato
I didn't fully understand Lua metatable mechanism.

I tought that the following example would allow me to use a table as if it was a function (note that there are two metatables):

mmt = {}
mmt.__index = mmt
function mmt.__call(tab,...) 
   print("called: ",tab,unpack(arg))
end

mt = {}
mt.__index = mmt
setmetatable(mt,mmt)

tab = {}
setmetatable(tab,mt)

Now, even if getmetatable(tab).__call is a function the instruction tab("xx") will fail. Reading the reference manual more carefully I noticed it states that "access to a metamethod does not invoke other metamethods" and that this is the expected behaviour. 

What I don't understand is the reason why. Efficiency? I would have found this feature very useful.


remo.D

P.S. The same goes for __add etc.



Reply | Threaded
Open this post in threaded view
|

Re: __call and metatables

Remo Dentato
Ops, there was a typo:

> mmt = {}
> mmt.__index = mmt
> function mmt.__call(tab,...)
>    print("called: ",tab,unpack(arg))
> end
> 
> mt = {}
> mt.__index = mt
> setmetatable(mt,mmt)
> 
> tab = {}
> setmetatable(tab,mt)



Reply | Threaded
Open this post in threaded view
|

Multiple Lua Script Files

Chris Gurtler
In reply to this post by Remo Dentato
I have an application which will load 2 or more Lua Script files and I would like to hold some data along with each script file.

As an example, my application calls lua_dofile file for each script as follows :-

lua_dofile(L1, "file_1")
lua_dofile(L2, "file_1")

Later in the code I have a function which is called from the script file, but I want to determine which file has made the call. I want to avoid doing something like the following in the function.

int my_c_function(lua_State *L)
{
    if (L == L1)
      printf("file 1 made the call");
   else if (L == L2)
      printf("file 1 made the call");
}

Does anyone know what is the most efficient way to do this ?

Regards,

Chris








Reply | Threaded
Open this post in threaded view
|

Re: Multiple Lua Script Files

CHU Run-min
IMHO, you should make a state variable which indicates the current
executed script file.


Reply | Threaded
Open this post in threaded view
|

Re: Multiple Lua Script Files

Chris Gurtler
Thank you,

Do you have an example of this?


CHU Run-min wrote:

IMHO, you should make a state variable which indicates the current
executed script file.






Reply | Threaded
Open this post in threaded view
|

Re: Multiple Lua Script Files

Ben Sunshine-Hill
In reply to this post by Chris Gurtler
On 1/13/06, Chris Gurtler <[hidden email]> wrote:
> I have an application which will load 2 or more Lua Script files and I
> would like to hold some data along with each script file.
>
> As an example, my application calls lua_dofile file for each script as
> follows :-
>
> lua_dofile(L1, "file_1")
> lua_dofile(L2, "file_1")
>
> Later in the code I have a function which is called from the script
> file, but I want to determine which file has made the call.

Well, you need to decide which you're REALLY trying to identify: the
file chunk which is at the top of your callstack, or the lua_State
it's executing in. For the former, you can use the debug functions.
The latter will require slightly more complicated methods (at least in
5.0).

Ben


Reply | Threaded
Open this post in threaded view
|

Re: Multiple Lua Script Files

CHU Run-min
In reply to this post by Chris Gurtler
#define FILE_1 1
#define FILE_2 2

int current_file;

current_file = FILE_1;
lua_dofile(L1, "file_1")
current_file = FILE_2;
lua_dofile(L2, "file_1")

int my_c_function(lua_State *L)
{
    if (current_file == FILE_1)
      printf("file 1 made the call");
   else if (current_file == FILE_2)
      printf("file 2 made the call");
}


Reply | Threaded
Open this post in threaded view
|

Re: Multiple Lua Script Files

Chris Gurtler
Hi,

Thanks for the tip, I think I've got it now.

Chris


CHU Run-min wrote:

#define FILE_1 1
#define FILE_2 2

int current_file;

current_file = FILE_1;
lua_dofile(L1, "file_1")
current_file = FILE_2;
lua_dofile(L2, "file_1")

int my_c_function(lua_State *L)
{
   if (current_file == FILE_1)
     printf("file 1 made the call");
  else if (current_file == FILE_2)
     printf("file 2 made the call");
}






Reply | Threaded
Open this post in threaded view
|

Re: Multiple Lua Script Files

Asko Kauppi
In reply to this post by Chris Gurtler

It's a bit different whether you load the script by -lmyscript or as myscript.lua.

Here's some code I use in Hamster, to come around this. Perhaps it will help?


local main= "main"    -- main script

-- Finding subscripts:
--
local LUA_PATH= rawget(_G,"package") and package.path
                                      or os.getenv("LUA_PATH")
if not LUA_PATH then
    error "LUA_PATH environment variable not set."
end

rawset( _G, "MY_PATH", false )

for pat in string.gfind( LUA_PATH, "[^;]+" ) do
    local try= string.gsub( pat, "?", "hamster" )

    local fh= io.open(try,"r")
    if fh then
        fh:close()
        MY_PATH= string.gsub(try,"hamster%.lua","")
        break
    end
end
assert(MY_PATH)

--
-- Actual application code:
--
local m= dofile( MY_PATH..main..".lua" )

return m


Chris Gurtler kirjoitti 14.1.2006 kello 5.09:

Thank you,

Do you have an example of this?


CHU Run-min wrote:

IMHO, you should make a state variable which indicates the current
executed script file.








Reply | Threaded
Open this post in threaded view
|

Re: Multiple Lua Script Files

Pavel Antokolsky aka Zigmar
In reply to this post by CHU Run-min
Hi,
Why to use globals? Why not to store the relevant information inside
the Lua state itself, for example in regisrty (if you don't want the
scipts been able to access it)?

For example

lua_pushstring(L1,file1);
lua_setfield(L1,LUA_REGISTRYINDEX,"scipt_filename");
lua_pushstring(L2,file2);
lua_setfield(L2,LUA_REGISTRYINDEX,"scipt_filename");
lua_dofile(L1, file1);
lua_dofile(L2, file2);

...
int my_c_function(lua_State *L)
{
    lua_getfield(L,LUA_REGISTRYINDEX,"scipt_filename");
    const char* script_name = lua_tostring(L,-1);
    ...
}

On 1/14/06, CHU Run-min <[hidden email]> wrote:
> #define FILE_1 1
> #define FILE_2 2
>
> int current_file;
>
> current_file = FILE_1;
> lua_dofile(L1, "file_1")
> current_file = FILE_2;
> lua_dofile(L2, "file_1")
>
> int my_c_function(lua_State *L)
> {
>     if (current_file == FILE_1)
>       printf("file 1 made the call");
>    else if (current_file == FILE_2)
>       printf("file 2 made the call");
> }
>


--
Best regards,
Zigmar