I'm struggling to understand why is the __gc metamethod is not being called here. I immediately removed the reference to x and triggered a GC, so why?
local obj = {}
obj.__index = obj
function obj:__gc()
print("gc")
end
function new()
return setmetatable({}, obj)
end
local x = new()
x = nil
collectgarbage()
I expect that the GC would collect that x and so it would trigger the __gc metamethod associated with it.
This is just a minimal reproducible example but to make my goals clear I want to wrap a C data in LuaJIT's ffi to deallocate its memory upon garbage collection.
I just found about ffi.metatype which allows me to attach a metatable with __gc e.g:
local ffi = require("ffi")
local mt = {}
local obj = ffi.metatype("struct { int x; }", mt)
function mt:__gc()
print("gc")
end
function new()
return obj(5)
end
local x = new()
x = nil
collectgarbage()
Since I need to wrap a C pointer, this is just right for me.
I don't think __gc is supported in the current version of LuaJIT, but it does seem to be planned as part of this really old proposal for a new GC:
https://github.com/LuaJIT/LuaJIT/issues/38, which is linked to this issue: https://github.com/LuaJIT/LuaJIT/issues/47#issuecomment-132403863
Related
I'm reviewing some toy examples from Lua and I found the following one over there with respect to environments:
M = {} -- the module
complex = {} -- global complex numbers registry
mt = {} --metatable for complex numbers
function new (r, i)
local cp = {}
cp = {r=r, i=i}
return setmetatable(cp,mt)
end
M.new = new -- add 'new' to the module
function M.op (...)
--Why does not it work?
local _ENV = complex
return ...
end
function M.add (c1, c2)
return new(c1.r + c2.r, c1.i + c2.i)
end
function M.tostring (c)
return string.format("(%g,%g)", c.r, c.i) --to avoid +-
end
mt.__tostring = M.tostring
mt.__add = M.add
complex.a = M.new(4,3)
complex.b = N.new(6,2)
--nil
M.op(a+b)
--It works
M,op(complex.a+complex.b)
The use of _ENV has no effect. However, if I use complex = _G, both lines work. How do set a local environment for M.op. I'm not asking for specific libraries, I just want to know why it does not work and how to fix it.
M.op(a+b)
This line doesn't do what you expect, because it uses values of a and b that are available when this method is called. It doesn't matter that you set _ENV value inside the method, as by the time the control gets there, the values referenced by a and b have already been retrieved and since both values are nil in your code, you probably get "attempt to perform arithmetic on global..." error.
how to fix it.
I'm not sure what exactly you want to fix, as you already reference the example that works. If you assign complex.a you can't assume that a will have the same value without mapping complex table to _ENV.
I have a table/object defined in Lua. I'm trying to add some methods from a C-API dll. I could attach the methods one at a time, but there are a lot of them. The last line of the code below is how I would like to do it. It is supposed to merge the methods into the Utilities object so that I don't have to do them one at a time. I'm getting the following error:
bad argument #1 to 'pairs' (table expected, got userdata)" const char *
Here is some sample code:
Utilities = {}
--
-- Other Code that defines/attaches methods to Utilities
--
-- Define some methods from my utilities.dll
local ffi = require("ffi")
ffi.cdef[[
void LogThis(const char * format, ...);
]]
local utilities_ffi = ffi.load("utilities")
-- This works
utilities_ffi.LogThis("hello world")
-- merge the two tables together (this fails)
for k,v in pairs(utilities_ffi) do Utilities[k] = v end
FFI must be returning a userdata object.
FFI library objects don't support iteration; you can't run pairs over them. You'll have to write an assignment for each function manually.
Also keep in mind that it's faster to access C functions directly from the library object, rather than storing them in a table (or even a local variable) and accessing them there. See the last section of the FFI tutorial.
Try this:
local function get(C, k)
return C[k]
end
function merge(C1, C2)
return setmetatable({}, {__index = function(t, k)
local ok, ret = pcall(get, C, k)
local v = ok and ret or C2[k]
t[k] = v --cache it
end})
end
Utilities = merge(utilities_ffi, other_ffi)
I'm trying to serialize and deserialize a Lua closure
my basic understanding is that the below factory should generate closures (and that Lua doesn't much distinguish between functions and closures -- i.e. there is no type 'closure')
> function ffactory(x) return function() return x end end
> f1 = ffactory(5)
> print(f1())
5 <-- so far so good
> s = string.dump(f1)
> f2 = load(s)
> print(f2())
table: 00000000002F7BA0 <-- expected the integer 5
> print(f2()==_ENV)
true <-- definitely didn't expect this!
I expected the integer 5 to be serialized with f1. Or, if string.dump can't handle closures, i expected an error.
I get quite different (but more what I expected) results with a mild change. It looks like f2 is indeed a closure, but string.dump didn't attempt to serialize the value of x at the time it was serialized.
The docs don't help me much. (what do they mean by "...with new upvalues"?)
> function ffactory(x) return function() return x+1 end end
> f1 = ffactory(5)
> print(f1())
6 <-- good
> s = string.dump(f1)
> f2 = load(s)
> print(f2())
stdin:1: attempt to perform arithmetic on upvalue 'x' (a table value)
stack traceback:
stdin:1: in function 'f2'
stdin:1: in main chunk
[C]: in ?
You can do something like this to save/restore those upvalues (note it doesn't handle upvalues shared between different functions):
local function capture(func)
local vars = {}
local i = 1
while true do
local name, value = debug.getupvalue(func, i)
if not name then break end
vars[i] = value
i = i + 1
end
return vars
end
local function restore(func, vars)
for i, value in ipairs(vars) do
debug.setupvalue(func, i, value)
end
end
function ffactory(x) return function() return x end end
local f1 = ffactory(5)
local f2 = (loadstring or load)(string.dump(f1))
restore(f2, capture(f1)) --<-- this restored upvalues from f1 for f2
print(f1(), f2())
This works under both Lua 5.1 and Lua 5.2.
Note an interesting result if you change ffactory slightly (added math.abs(0); anything that uses global table in any way will do):
function ffactory(x) return function() math.abs(0) return x end end
Now if you restore upvalues you get the same result, but if you don't restore upvalues you get a run-time error under Lua 5.2:
lua.exe: upvalues.lua:19: attempt to index upvalue '_ENV' (a nil value)
stack traceback:
upvalues.lua:19: in function 'f2'
upvalues.lua:24: in main chunk
[C]: in ?
the docs are pretty clear. string.dump doesn't handle closures using upvalues. this is because the upvalues could be anything (including userdata, and how would Lua know how to serialize that?)
upvalues are the external variables that are local to a function due to scoping/closures. since x in your example is an upvalue to the function returned by ffactory, it does not get serialized.
if you want to support this somehow, you would have to store the upvalues yourself and set them again after you've deserialized the function, like this:
function ffactory(x)
return function() return x+1 end
end
local f1 = ffactory(5)
print(f1())
local s = string.dump(f1)
f2 = loadstring(s)
debug.setupvalue(f2, 1, 5)
print(f2())
I am creating functions (of x) from a string in Lua. The code I am using is
function fcreate(fs)
return assert(loadstring("return function (x) return " .. fs.." end"))()
end
This works for globals, e.g.
u=fcreate("math.sin(x)")
does the right thing.
However, it does not seem to like local variables. So
local c=1
u=fcreate("math.sin(x)+c")
will not work because c is local.
Is this fixable?
"loadstring does not compile with lexical scoping", so no, it can't see locals outside the loadstring call.
Is this fixable?
That depends. Why are you using loadstring in the first place? Lua supports closures as first class values, so I can't see from your example why you'd need loadstring.
Your example:
u = fcreate("math.sin(x)+c")
Can be rewritten without the need for loadstring or your fcreate function:
u = function(x) return math.sin(x)+c end
Which of course is the same as:
function u(x) return math.sin(x) + c end
I can see a case for loadstring if you have user-configurable expressions that you wanted to compile into some other function, but your case with the local c suggests that's not the case. Are you trying to make some kinda of home-rolled lamda syntax?
Can't be done in any reasonable way. For an example of why, look at this:
function makefunction(name)
local a = 1
local b = 2
local c = 3
-- ...
return assert(loadstring("return " .. name))
end
local a = 4
local func = makefunction("a")
print(func())
If this worked, what is printed? 1 or 4? Does it capture the variable from the place where the function was loaded, even though that function doesn't exist anymore? Or does it look it up from the place where it was called?
The first would mean that the function is lexically scoped wherever it's created. Being able to access the variable after the function has exited means that the variable would need to be promoted into an upvalue dynamically, which is not something that Lua can do at the moment. As it is now, Lua can see every access to a local variable during compilation, so it knows which variables to turn into upvalues (at a performance hit) and which to keep as locals.
The second would mean that variable accesses inside a loadstring'd function would work completely different than every other access in Lua: Lua uses lexical scoping, not dynamic scoping. It'd be a huge implementation change in Lua, and an extremely inconsistent one.
So, neither is supported. You can control the environment of a dynamically loaded function, using setfenv in Lua 5.1 or the env parameter of load(...) in Lua 5.2, but neither of those let you access local variables automatically.
Something you could do if you don't need to mutate the local variables is to pass those values as arguments to the generated function. You would still need to manually specify the variables to close over but its better then nothing.
For example, you can build up your closure to look like
return (function(a,b,c)
return function(x) return print(a, x) end
end)(...)
We might do that by changing your function to look like
function fcreate(variables, fs)
local varnames = {}
local varvalues = {}
local nvars = 0
for n,v in pairs(variables) do
nvars = nvars + 1
table.insert(varnames, n)
table.insert(varvalues, v)
end
local chunk_str = (
'return (function(' .. table.concat(varnames, ',') .. ') ' ..
'return function(x) return ' .. fs .. ' end ' ..
'end)(...)'
)
return assert( loadstring(chunk_str) )( unpack(varvalues, 1, nvars) )
end
local a = 1;
local f = fcreate({a=a}, 'x+a')
print(f(1), f(2))
I'm just getting started with Lua. In the example I'm learning from (the Ghosts & Monsters Corona open source), I see this pattern repeatedly.
local director = require("director")
local mainGroup = display.newGroup()
local function main()
mainGroup:insert(director.directorView)
openfeint = require ("openfeint")
openfeint.init( "App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here" )
director:changeScene( "loadmainmenu" )
return true
end
main()
Is this some sort of convention experienced Lua programmers recommend or are there genuine advantages to doing it this way? Why wouldn't you just skip the function all together and do this:
local director = require("director")
local mainGroup = display.newGroup()
mainGroup:insert(director.directorView)
local openfeint = require ("openfeint")
openfeint.init( "App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here" )
director:changeScene( "loadmainmenu" )
Is there some implicit benefit to the first style over the second? Thanks!
Is this some sort of convention experienced Lua programmers recommend or are there genuine advantages to doing it this way?
It's not typical. The advantage is that object state is private, but that's not enough of an advantage to recommend it.
I see this pattern repeatedly.
I've never seen it before, and it happens only once in the source you posted.
EDIT: Adding a response to a question asked in the comments below this post.
A function which accesses external local variables binds to those variables and is called a 'closure'. Lua (for historical reasons) refers to those bound variables as 'upvalues'. For example:
local function counter()
local i = 1
return function()
print(i)
i = i + 1
end
end
local a, b = counter(), counter()
a() a() a() b() --> 1 2 3 1
a and b are closures bound to different copies of i, as you can see from the output. In other words, you can think of a closure as function with it's own private state. You can use this to simulate objects:
function Point(x,y)
local p = {}
function p.getX() -- syntax sugar for p.getX = function()
return x
end
function p.setX(x_)
x = x_
end
-- for brevity, not implementing a setter/getter for y
return p
end
p1 = Point(10,20)
p1.setX(50)
print(p1.getX())
Point returns a table of closures, each bound to the locals x and y. The table doesn't contain the point's state, the closures themselves do, via their upvalues. An important point is that each time Point is called it creates new closures, which is not very efficient if you have large quantities of objects.
Another way of creating classes in Lua is to create functions that take a table as the first argument, with state being stored in the table:
function Point(x,y)
local p = {x=x,y=y}
function p:getX() -- syntax sugar for p.getX = function(self)
return self.x
end
function p:setX(x)
self.x = x
end
return p
end
p1 = Point(10,20)
p1:setX(50) -- syntax sugar for p1.setX(p1, 50)
print(p1:getX()) -- syntax sugar for p1.getX(p1)
So far, we're still creating new copies of each method, but now that we're not relying on upvalues for state, we can fix that:
PointClass = {}
function PointClass:getX() return self.x end
function PointClass:setX(x) self.x = x end
function Point(x,y)
return {
x = x,
y = y,
getX = PointClass.getX,
setX = PointClass.getY,
}
end
Now the methods are created once, and all Point instances share the same closures. An even better way of doing this is to use Lua's metaprogramming facility to make new Point instances automatically look in PointClass for methods not found in the instance itself:
PointClass = {}
PointClass.__index = PointClass -- metamethod
function PointClass:getX() return self.x end
function PointClass:setX(x) self.x = x end
function Point(x,y)
return setmetatable({x=x,y=y}, PointClass)
end
p1 = Point(10,20)
-- the p1 table does not itself contain a setX member, but p1 has a metatable, so
-- when an indexing operation fails, Lua will look in the metatable for an __index
-- metamethod. If that metamethod is a table, Lua will look for getX in that table,
-- resolving p1.setX to PointClass.setX.
p1:setX(50)
This is a more idiomatic way of creating classes in Lua. It's more memory efficient and more flexible (in particular, it makes it easy to implement inheritance).
I frequently write my own Lua scripts this way because it improves readability in this case:
function main()
helper1( helper2( arg[1] ) )
helper3()
end
function helper1( foo )
print( foo )
end
function helper2( bar )
return bar*bar
end
function helper3()
print( 'hello world!' )
end
main()
This way the "main" code is at the top, but I can still define the necessary global functions before it executes.
A simple trick, really. I can't think of any reason to do this besides readability.
The first style could be used too improove readability, but I would rather give the function some meaningful name instead of main or just go without the function.
By the way, I think it's always a good practice to name blocks of code, i.e. put them into functions or methods. It helps explain your intend with that piece of code, and encourages reuse.
I don't see much point to the first style as you've shown it. But if it said something like if arg then main() end at the bottom, the script might (just might) be useful as a loadable "library" in addition to being a standalone script. That said, having a main() like that smacks of C, not Lua; I think you're right to question it.