lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi Mike,

I'm no expert on Lua's C API, but the code you posted looks to me like
it should work. I don't think it's necessary to pop off the table
itself (what you call 'method') from the stack before calling the
function, Lua should ignore whatever is on the stack below the
function you're calling.

The only thing is, from the example "bugs:attackUnit" you mentioned,
from the colon (as opposed to a dot like in "bugs.attackUnit") it
seems that the function attackUnit requires a reference to self, in
addition to the userdata argument it receives. That is,
"bugs:attackUnit(target)" (notice the colon) is equivalent to
"bugs.attackUnit(bugs, target)" (notice the dot and the extra
argument). This is where "self" comes from in Lua methods, it's the
hidden first argument if you use the colon-notation.

So, the table where you get the function from, should itself also be
passed as an argument to that function. As the very first argument, to
be exact. So in this part of your code:

        if ( lua_isfunction(L, -1) ) {

            Lunar<Unit>::push(L, pUnit);
            lua_pcall(L, 1, LUA_MULTRET, 0);

            return;

        } else { //...etc.

...you should make the following changes (untested):

        if ( lua_isfunction(L, -1) ) {

            lua_pushvalue(L, -2); // <--- *** Add this line. ***
            Lunar<Unit>::push(L, pUnit);
            lua_pcall(L, 2, LUA_MULTRET, 0); // <--- *** Number of
arguments is now 2! ***

            return;

        } else { //...etc.

What lua_pushvalue does is, it pushes onto the stack a copy of the
element at the given stack index. In the above code, it pushes a copy
of the table reference that was at index -2, which was where you
obtained the function from, and which now becomes the first argument.
The userdata then becomes the second argument. The pcall is also
updated to reflect the extra argument.

If this doesn't fix your problems, check to make sure that the strings
you're using to find the table and function, are actually correct
(since you're doing some string manipulation to obtain them).
Otherwise, I think you'll have to provide more details as to what
exactly happens when you run your code.

Hope this helps!

Regards,
Mark


2009/2/18 Mike Killingbeck <mkillin@gmail.com>:
> Hi, first I'm new here, never used a mailing list before so bare with my
> retardation. Also, I don't know C++ worth a crap but I've been learning by
> hands on tinkering trying to play with a particular C++ function. Shoot I'll
> just spit it right now:
>
> I am trying to call a function in a Lua table, from C++. Examples. (this
> works fine)
> let funcname equal a const char representative of a function name.
>
> lua_pushstring(L, funcname);
> lua_gettable(L, LUA_GLOBALSINDEX);
> if(lua_isnil(L,-1))
> {
>     printf("Tried calling invalid Lua function '%s'\n", funcname);
>     return;
> }
>
> Lunar<Unit>::push(L, pUnit);
> lua_pcall(L, 1, LUA_MULTRET, 0);
> return;
>
> The above code snippet works fine provided that 'funcname' is of course a
> valid function on the global stack. It properly calls the function passing
> it a userdata argument. However, if I was to pass into 'funcname' a string
> that represents a method, for example "bugs:attackUnit", it doesn't seem to
> call the function. I wrote some code to split the string into two parts,
> then push the first part to the stack, check its relevancy, then push the
> second part to stack, check its relevancy as a function, then call that
> function in the same way as above, doesn't work, example:
>
> string str = funcname;
> int md1 = str.find(':');
>
> if ( md1 > 1 ) {
>     string method = str.substr(0, md1);
>     string funname = str.substr(md1+1);
>
>     lua_getglobal(L, method.c_str() );
>     if ( lua_istable(L, -1) ) {
>
>         lua_pushstring(L, funname.c_str());
>         lua_rawget(L, -2);
>
>         if ( lua_isfunction(L, -1) ) {
>
>             Lunar<Unit>::push(L, pUnit);
>             lua_pcall(L, 1, LUA_MULTRET, 0);
>
>             return;
>
>         } else {
>             printf("Invalid function '%s:%s'", method.c_str(),
> funname.c_str());
>             return;
>         }
>
>     } else {
>         printf("Invalid table '%s'\n", method.c_str());
>         return;
>     }
> }
>
> it doesn't seem to work and I don't quite understand why as I'm passing it
> all the same information (so to speak) as the first example. The only
> difference I can think of is that the Lua stack has an extra element in it,
> and that being the table from the getglobal(L, method.c_str()). So if my wee
> brain is right my stack should be something like:
>
> pUnit <- userdata
> funname <- function in table method ( method[funname] )
> method <- Lua table
>
> where as the first example would be like:
>
> pUnit <- userdata
> funcname <- Lua function
>
> What am I doing wrong, should I be popping 'method' off the stack, first
> before pushing my pUnit to the stack, then calling the function? I've
> tinkered with this for hours and although it isn't a big deal it does help
> me understand the Lua stack and how to work with Lua in C++.
> Basically, all I want to do is call a function from a table and pass it a
> userdata as an argument. I've done the RTFM but that thing is pretty much
> useless unless you are already seasoned. I've gone over countless forums
> looking for examples but ALL I find are how to get data from a lua table in
> C++. Which I can do fine, without any issues but when it comes to calling a
> function from within a Lua table, nadda, or at least the day I spent looking
> and reading just wasn't enough... aarrrrgh.
>
> Any help would be much appreciated!
>
> Mike
>