Jump to content
  • Advertisement
Sign in to follow this  
Morbular

Lua Function Calls from C++

This topic is 3404 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, Recently, I've just started to learn about the Lua API, and I have come across a problem. My goal is to call a function "onLoad" in two loaded files. The function exists in both files. For example: =========================== Lua Code: File1.lua:
function onLoad( )
    output ( "Loaded file one!" ) -- custom function
end

-- More code


Lua Code: File2.lua:
function onLoad( )
    output ( "Loaded file two!" ) -- custom function
end


C++:
void LoadLUA() {
    lua_State* L;
    L = lua_open();
    luaL_openlibs(L);
    lua_register(L,"output","Print");

    // Load the first file
    luaL_dofile(L,"File1.lua");

    // Load the second file
    luaL_dofile(L,"File2.lua");

    // Now, call the callback
    lua_getglobal(L,"onLoad");
    if(!lua_isfunction(L,-1)) return;
    lua_call(L,0,0);
}


The problem arises when it calls only the callback in File2.lua, the first file to be loaded by the Lua API. I would like the callback to also be called in File1.lua, however, I have no idea of how to accomplish this. I theorize that a lua thread would solve this issue, but still, I would not know where to begin. Does anybody have any suggestions? [Edited by - Morbular on January 23, 2009 7:02:12 PM]

Share this post


Link to post
Share on other sites
Advertisement
Morbular,

From the top of my head, you should be loading a file, calling it's function and then loading the next file. Though to me this should mean that only your File2 would load.

ie.

// Load the first file
luaL_dofile(L,"File1.lua");

// Now, call the callback
lua_getglobal(L,"onLoad");
if(!lua_isfunction(L,-1)) return;
lua_call(L,0,0);

// Load the second file
luaL_dofile(L,"File2.lua");

// Now, call the function in second file.
lua_getglobal(L,"onLoad");
if(!lua_isfunction(L,-1)) return;
lua_call(L,0,0);




This is how I do it. It might not be efficient (I dont know), but it works for me.

Good luck,

Share this post


Link to post
Share on other sites
This isn't easy to do in Lua, it's essentially loading up 2 files with the exact same named function and asking Lua to tell them apart. There are many ways to do something similar to this in Lua without having to hack around using Lua threads and new global tables ( which isn't desirable anyways since you'll proably want to access the same globals across these scripts ).

Method A: stuff your function in a context container object which is presumed to always exist ie something called self.

so

1)before u load up ur script push in the current self object like so ( in ur scripts )

self = SELF_MNGR:getSelf(selfID);

2)within the script ur loading modify it to look like this.

function onLoad( )
output ( "Loaded file one!" ) -- custom function
end

self.onLoad = function onLoad( ); end

3)to execute the onLoad of this particular funciton you'll now use the self object which can be conviently stored and maniupated, like so

local otherSelf = SELF_MNGR:getSelf(selfID);

--viola, execute onload
otherSelf.onLoad();

Method B: simlar to method A, but instaed of using presumed self object you can use a global manager and execute some code to push up the loaded functions into a registry like so:


function onLoad( )
output ( "Loaded file one!" ) -- custom function
end

--pushes new function, context is already presumed to be set
FUNC_MNGR:pushOnLoad(function onLoad( ); end);

you can now invoke the onLoad through the manager using the current context. The current context is just like the self object its just a simple table you use to store away the functions into a unique namespace, so overlaping global names don't matter anymore.

Since you never execute the global onLoad, its okay to replace it everytime you load up a new script, just follow that paradigme.

This should allow you to write very standardized scripts whose context is set outside of Lua ( by say C++ object manager etc.. )

Good Luck!

BTW: you'll proably want to clear out old global functions between invokation of the scripts to prevent accidental registartion of residual global functions.

I just realised that self is a keyword of Lua, so you'll be better off using something other than self.

-ddn

[Edited by - ddn3 on January 25, 2009 1:12:45 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Morbular
Hello,

Recently, I've just started to learn about the Lua API, and I have come across a problem. My goal is to call a function "onLoad" in two loaded files. The function exists in both files. For example:

===========================
Lua Code:
File1.lua:
*** Source Snippet Removed ***

Lua Code:
File2.lua:
*** Source Snippet Removed ***


C++:
*** Source Snippet Removed ***

The problem arises when it calls only the callback in File2.lua, the first file to be loaded by the Lua API. I would like the callback to also be called in File1.lua, however, I have no idea of how to accomplish this. I theorize that a lua thread would solve this issue, but still, I would not know where to begin.

Does anybody have any suggestions?


first understand the problem.
when you load a LUA file, you're not tying the code to a file. So, if you have:
LUA_FILE_A:

function onLoad( )
output ( "Loaded file one!" ) -- custom function
end


what you really are doing is setting a global "variable" called onLoad, that points to the code above.

So, if you load another ten thousand files, and one of them has something like:

function onLoad( )
output ( "Loaded file two!" ) -- custom function
end

Now variable onLoad is pointing to the above function, and the first one ceeses to exists.

If all you want is to run that function each time you load a file, just call it in the endof the file.

FILE XPTO:

function onLoad( )
output ( "Loaded file two!" ) -- custom function
end
...
lots of code
...
onLoad()

Share this post


Link to post
Share on other sites
What Morbular is asking is actually done in a game in development called Balding's Quest. I don't know the details of the C++ implementation, but I always guessed that after loading an object (and the associated global functions), the C++ code would get a handle to each relevant function and store them in the game-object (not as global functions). Oh I forgot to mention that each file is an object in this game [smile] Might make things easier! Either that or create a vector of handles to OnLoad() functions, then another vector of handles to OnButtonPress(), etc.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jotaf
What Morbular is asking is actually done in a game in development called Balding's Quest. I don't know the details of the C++ implementation, but I always guessed that after loading an object (and the associated global functions), the C++ code would get a handle to each relevant function and store them in the game-object (not as global functions). Oh I forgot to mention that each file is an object in this game [smile] Might make things easier! Either that or create a vector of handles to OnLoad() functions, then another vector of handles to OnButtonPress(), etc.


you could do that by changing environment before loading each file, or by doing something like:

FILE_A:

local T={};

T.onLoad = function blabla


return T


and on main program:

local var=require("file_a")

this way, each file is mapped to a var.
There are really several approaches.

edit: What I was trying to explain in the previous post was not HOW to do it, but WHY it doesnt work. Else, you just giving someone a fish, not explaining him how to fish. :)



[Edited by - mystb on January 24, 2009 8:28:52 AM]

Share this post


Link to post
Share on other sites
This is more of a convience for non-programmers. They write basic function hooks within a single file which acts within a single context. All the functional hooking and binding can be done automatically by external load code so the user ( designer ) doesn't have to worry about function registeration or anything like that ( you can also add safety checks to make sure they didn't mispell the functions and all ).

Mosttly designers these days are a cross of desinger/programmer as scripting is so fundemental to games these days. This type of approach isn't very common in large games anymore since it's not very tractable or efficient. They use a more comprehensive componenet based system with runtime function bindings to define behavior from what i've seen.

Good Luck!

-ddn

Share this post


Link to post
Share on other sites
ddn3: You're right, it can be seen as a mere convenience. But defining a local context is useful for programmers too. Why would C++ have an extra keyword for "namespaces" then? It's good programming practice. Scripts don't have to be messy just because they're not "real programming" [smile] I like the idea of what the OP is trying to achieve.

mystb: Pá ele mostrou que percebia isso logo de início. Repetir a descrição do problema não é grande ajuda, e se toda a gente chegasse sozinha à solução nem havia foruns, né...

Share this post


Link to post
Share on other sites
Quote:
Original post by Jotaf

mystb: Pá ele mostrou que percebia isso logo de início. Repetir a descrição do problema não é grande ajuda, e se toda a gente chegasse sozinha à solução nem havia foruns, né...

Well, the OP suggested, to me, that he knew what was happening, but didn't really understand why.
ddn3 gave him some solutions, I just tried to explain the why, not redescribing the problem. I think both answers helped: one provided some ideas for a solution, the other provided some insight on the actual problem.

And IMHO, you foreign language post is somewhat less helpfull is this thread, than mine. But opinions are just that, opinions.
Take care!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!