lua-users home
lua-l archive

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

On Fri, 12 Feb 2010 13:13:05 +0100
spir <> wrote:

> Hello,
> I'm looking for a way to "subtype" Lua files, for file objects to hold additional attributes. It seems I cannot directly set attributes on Lua Files, since they are userdata. Is there a way to write a custom file type that delegates file methods to an actual Lua file (open in mode 'r')? My trials using __index with a table or function launch errors like:
> lua: _essai.lua:44: calling 'read' on bad self (FILE* expected, got table)
> stack traceback:
> 	[C]: in function 'read'
> 	_essai.lua:44: in main chunk
> 	[C]: ?
> How should I write __index to call a method on a *FILE?
> Denis


thank you for you hints.

@ Per: If I understand correctly, I think your solution is more or less what I tried to do; if true, then this does not work because Lua file objects are userdata, not tables. For instance, storing the Lua file in a field and setting a metatable on my custom file objects such as
{__index = File.method}
File.method = function(f,name) return f._luaFile[name] end
precisely raises the  error above. (Indeed, the same happens with {__index = f._luaFile}.)

@ Tom: While I think I understand the use of weak tables, I don't get why/how it should solve the issue.

@ Steve: Well, your solution is the only one as of now. Below an example, in which the need for additional attributes is illustrated by the sole .name, here used in .tostring.

require "io"
luaReadFile = function(name) return, 'r') end

-- def of File
File.tostring = function(f) return 'File"''"' end = function(f, ...) return f._luaFile:read(...) end
File.lines = function(f, ...) return f._luaFile:lines(...) end
File.close = function(f, ...) f._luaFile:close(...) end
file_mt = {__tostring=File.tostring, __index=File}
File.create = function(_, name)
	local luaFile = luaReadFile(name)
	local f = {name=name, _luaFile=luaFile}
	setmetatable(f, file_mt)
	return f
File_mt = {__call=File.create}
setmetatable(File, File_mt)

-- use
f = File"test"
print (f)
for i=1,5 do print (f:read()) end


la vita e estrany