1

I'm writing a "C" userdata array structure. As setter and getter i want normal array access (u[0] = 1 u[0]) like it's discussed here: [c array share][1]Share Array between lua and C. For that i need to set __index and __newindex to the set and get functions in c.

Additional i want object-oriented access, too, "like u:mymethod()". My trouble is, that i need to set now __index to the metatable itself.

Is there a way, to achieve both?

2
  • Why do you need your __index to be the metatable? It is easier if you keep them separate. Commented May 1, 2013 at 16:05
  • I read it here: lua.org/pil/28.3.html. But yes, i don't need it. Commented May 1, 2013 at 20:45

1 Answer 1

4

Just one of many possible ways to achieve this:

local userdata = { _array = { "A", "B", "C" } }
local mt = { }
local methods = { }

function mt.__index(userdata, k)
    if methods[k] then
        return methods[k]
    else
        return rawget(userdata, "_array")[k]
    end
end

function mt.__newindex(userdata, k, v)
    if methods[k] then
        error "can't assign to method!"
    else
        rawget(userdata, "_array")[k] = v
    end
end

function methods.count(userdata)
    return #rawget(userdata, "_array")
end

setmetatable(userdata, mt)

userdata[3] = "Z"

print(userdata[1])
print(userdata[2])
print(userdata[3])
print(userdata:count())

userdata.count = 0

edit: As lhf pointed in his comment, it is not dangerous to use metatable as it's __index table at all, because c-methods should always check on what self they operate.

Sign up to request clarification or add additional context in comments.

2 Comments

Uisng the metatable as __index is not dangerous per se. I do it all the time. You only have to take a bit of care in metamethods to make sure you get userdata of the correct type. But you have to do it anyway, because one can always call getmetatable(u).__gc(u) unless you protect the metatable.
Oh, glad to meet you, Mr. de Figueiredo! I absolutely forgot that luaL_checkudata() protects us from such errors. I'll edit my answer accordingly. Thank you for this great project, sir!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.