lua-users home
lua-l archive

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


On Nov 19, 2007 10:50 AM, Paulo Lopes <pmlopes@gmail.com> wrote:
> Hi,
>
> I'm trying to make my C library Lua aware but the problem is that it
> relies on lots of global variables to change all its internal state. I
> diged the list and found some code that was supposed to help me out,
> but now that i compiled it it fails because I think it was old Lua 4.x
> code and it isn't compatible with Lua 5.x

You shouldn't rely on global variables to create a library. They are a
generally messy way to program, they are not shared between programs
that link with the library, and if you ever use threads someone will
have to write extra functions to avoid race conditions. An ideal
library should consist mostly of reentrant functions that take a state
as their first argument, like the Lua library itself.

That being said, in Lua 5 (actually since Lua 4.1) metatables and
metamethods replace tags and fallbacks. An example:

  -- Expose library variables as get/set pairs.
  -- This assumes the getSomeVar and setSomeVar lua_CFunctions were exposed
  -- from C, typically by using luaL_register.

  local libVariables = {
    someVar = {
      get = getSomeVar,
      set = setSomeVar
    }
  }

  -- This metatable will define fallback behaviour for our Lua environment.
  local libMetatable = {}

  -- The __index metamethod.
  -- Triggered when reading a free table index (or indexing a userdatum).
  function libMetatable:__index(name)
    local var = libVariables[name]
    if var then
      return var.get()
    else
      error("attempt to get an undefined library variable: ", var)
    end
  end

  -- The __newindex metamethod is the counterpart to __index for write access.
  function libMetatable:__newindex(name, value)
    local var = libVariables[name]
    if var then
      var.set(value)
    else
      error("attempt to set an undefined library variable: ", var)
    end
  end

  -- Let's use the library in a dedicated environment.
  -- The print function is included to for test purposes.
  -- Other indexes are resolved by the metatable.
  setfenv(1, setmetatable({print = print}, libMetatable))

  someVar = 42      -- triggers __newindex("someVar", 42) --> setSomeVar(42)
  print(someVar)    -- triggers __index("someVar") --> return getSomeVar()

You will find extensive developments in the must-read book by Roberto,
Programming in Lua, at http://www.lua.org/pil/ .

Happy learning !

--
-- Thomas