lua-users home
lua-l archive

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



> Hi all (especially Nick Trout and Jon Belmonte who have been trying to
> drag me to use lua for quite a while now),

Finally... ;-)

> Well, version 5 has finally got the features I need it seems, so I'm
going
> to give it a go.

Yes, it does seem to have come on rather a lot since version 4.
Practically tailored for writing games now.

> I may have read the documentation wrong, but I don't like the way lua
lets
> all lua co-routines/functions have access to the global scope.
> 
> Is there a way to have multiple global scopes, so I don't have to
worry
> about script writers breaking other people's data or accessing stuff
they
> shouldn't?  I'd like to keep these "global" scopes local to each
object
> (and
> have multiple coroutines running within the same "space" on an
object).

Here is an example in Lua script. I find it easier to work with this
than the C API and stacks etc. You can always convert it later...
(Thanks to Peter anyway)


-- this bit operates as you would expect:

g = 1

function foo()
    local a = 1
    while a<=3 do
        print('co', a, g)  -- output
        coroutine.yield()
        a = a+1
        g = g+1
    end
end

co = coroutine.create(foo)
while coroutine.resume(co) do
end


Output is:
co	1	1
co	2	2
co	3	3

--------------------------------- Example 2 ------------------------

Now we move into "foospace". Here we create our global variable space
"vars" and a function getg to control access. We first look in our
"local global" space for our variable and then fall back on the real
global space if a variable isn't found there (i.e. "return
rawget(vars,n) or rawget(_G,n)")

g = 1

function foospace()
    local vars = { g=100 }
    local getg = function(t,n) return rawget(vars,n) or rawget(_G,n) end
    local foo = function ()
        local a = 1
        g2 = 200 -- new global
        while a<=3 do
            print('co', a, g, g2)  -- output
            coroutine.yield()
            a = a+1
            g = g+1
        end
    end
    setfenv(foo, setmetatable(vars, { __index=getg }))
    foo()
end

co = coroutine.create(foospace)
while coroutine.resume(co) do
end
print(g,g2) -- see if global scope changed.


Output is:
co	1	100	200
co	2	101	200
co	3	102	200
1	nil  -- ie. We didn't touch the real global scope.

You can pretty much set up any environment you could imagine really. The
great thing is you can create function to create your coroutine and it
returns it tailored to its use. You could restrict creation of new
objects using __newindex. I'm pretty new to setfenv() since it's not
really been in the scope of our project. So using the above style you
wouldn't need multiple lua_States - which may or may not be a
disadvantage. We're using one lua_State for each (mutually exclusive)
"mission" which allows easy tidy up and the mission shouldn't really be
affecting the global world state - and if so you should know about it.

I've been working on a tutorial. Hope the following material is useful:
http://lua-users.org/wiki/MetamethodsTutorial
http://lua-users.org/wiki/ObjectOrientationTutorial

and more generally:

http://lua-users.org/wiki/TutorialDirectory


> Also, if this is possible, what kind of overhead (memory
> footprint/creation
> time) does the lua_state structure have? (I presume I'll need
multiples of
> these)

They're quite small. I don't know what's more efficient, multiple
lua_States or one lua_State with multiple coroutines. One might be more
memory efficient and the other less computationally expensive?

> Bear in mind this stuff might be in the documentation and I just
haven't
> got
> there yet, be kind with me. :-)

Have a look at the tutorial and if there's anything missing give me a
shout.

Nick