Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7693679
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 31, 20262026-05-31T21:08:43+00:00 2026-05-31T21:08:43+00:00

I am using [actually learning to use] the Lua C api. I’m new to

  • 0

I am using [actually learning to use] the Lua C api. I’m new to Lua so apologies if I have some terminology incorrect, and would appreciate any corrections to it.

I have an empty Global table G which I create using lua_setglobal at some point on init. G’s __index points to a C function, which I believe is called a metamethod. When invoked, this function creates a new lightuserdata item that it inserts into the G global table.

So, if my understanding is correct, G.foo will result in an invocation of G’s __index metamethod and foo will be created by it and added to G. Future invocations to G.foo will no longer need to call the metamethod since it would find foo to exist in G.

Now, when creating foo, I associate a metatable to the newly created lightuserdata (foo) by setting its __index to an array of C functions which contains, most notably, ‘set’ and ‘get’. The idea is, whenever foo:get() is invoked, foo’s metatable should be looked up to call the C function to get its value, etc.

Here’s the (normal) behaviour I see:

  • Invoke G.foo from a lua file.

    This creates foo using G’s metamethod as expected.

  • Then, invoke G.foo:get()

    Since foo is already a part of G (previous step), G’s metamethod is not invoked, as expected. Instead, foo’s metatable is checked and the C function corresponding to ‘get’ is invoked. This is also as expected, and is exactly how I want it to work.

However, if I do this:

  • Invoke G.foo:get() directly without first invoking G.foo

    Then, it invokes G’s metamethod twice, once for foo (expected) and once for ‘get’ (not expected). I don’t want ‘get’ to be processed by G’s __index metamethod. It basically tries to create a new lightuserdata called ‘get’ (just like it did for ‘foo’) and so on, which is not what I want to do. I’d like the newly created foo’s metatable to be looked up so that the proper ‘get’ C function is invoked for foo.

I’ve simplified my use case in order to make the issue most obvious, and so I hope its understandable enough. Also, would appreciate if you can point me to any lua documentation or feature reference that would help me understand why this happens.

Edit:
Adding some code with relevant parts to demonstrate what I am doing:

static void init()
{
    lua_newtable( luaVM );
    lua_createtable( luaVM, 0, 0 );             
    lua_pushcfunction( luaVM, lua_metaMethod );
    lua_setfield( luaVM, -2, "__index" );
    lua_setmetatable( luaVM, -2 );          
    lua_setglobal( luaVM, "G" );    
}

static const luaL_reg lua_methods[] =
{
    {   "set",      lua_set },
    {   "get",      lua_get },      
    {0, 0}
};

static int lua_metaMethod( lua_State *luaVM )
{
    // I get "foo" by using lua_tostring( luaVM, 2 ), and store that in 'name'.
    // I then lookup 'fooData', which is a pointer to data associated with foo that I want to add to G.

    lua_getglobal( "G" );
    lua_pushlightuserdata( luaVM, ( void* ) fooData );
    lua_createtable( luaVM, 0, 0 );
    lua_createtable( luaVM, 0, 0 );
    luaL_register( luaVM, NULL, lua_methods );              // Trying to make sure foo:get() calls one of these, etc.
    lua_setfield( luaVM, -2, "__index" );
    lua_setmetatable( luaVM, -2 );
    lua_setfield( luaVM, -2, name );

    return 1;
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-31T21:08:45+00:00Added an answer on May 31, 2026 at 9:08 pm

    Given the code as you have described it, the problem is with lua_metaMethod (BTW: it is a bad idea to name your functions lua_. That’s a prefix reserved for Lua API functions).

    The return value from the __index metamethod will be returned to the user. So if the user says G.foo, then the return value from G‘s __index metamethod will be returned.

    What does lua_metaMethod return? It returns exactly 1 return value. And since parameters passed to the function are the first on the stack, it will return the first parameter. The first parameter to the __index metamethod is always the table the metamethod is invoked on. In your case, this table is the table stored in G.

    Therefore, G.foo will return G. Therefore, G.foo:get() is equivalent to G:get() (though the first version does have an extra metamethod call). I’m guessing that’s not what you want 😉

    What it should return is the light userdata that was just stored in G["foo"].

    Consider this code instead.

    static int lua_metaMethod( lua_State *luaVM )
    {
        //We won't use this, so only do this if you need the string.
        const char *name = lua_tostring(luaVM, 2); 
    
        // I then lookup 'fooData', which is a pointer to data associated with foo that I want to add to G.
    
        //No need to get G. We already have it: the first parameter.
        lua_pushlightuserdata( luaVM, ( void* ) fooData );    //Stack: table, key, userdata
        lua_createtable( luaVM, 0, 0 );                       //Stack: table, key, userdata, {}
        lua_createtable( luaVM, 0, 0 );                       //Stack: table, key, userdata, {}, {}
        luaL_register( luaVM, NULL, lua_methods );              // Trying to make sure foo:get() calls one of these, etc.
        lua_setfield( luaVM, -2, "__index" );                 //Stack: table, key, userdata, {}
        lua_setmetatable( luaVM, -2 );                        //Stack: table, key, userdata
    
          //Stack now contains: table, key, userdata.
        lua_insert(luaVM, 2);                //Stack: table, userdata, key
        lua_pushvalue(luaVM, -2);            //Stack: table, userdata, key, userdata
        lua_rawset(luaVM, 1);            //Use rawset because table has a metatable. It's probably best not to invoke it.
    
          //Stack now contains: table, userdata.
        lua_insert(luaVM, 1);                 //Stack: userdata, table.
    
        return 1;  //Return just the userdata. `table` will be discarded.
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm new to using appdomains, so I'm learning as I go. I'm making use
I'm actually using Doctrine2 within a Zend Framework project. I'm build an API to
I'm new to Visual C# Studio (actually using the Express edition, but another developer
I want to use draggable feature of jQuery UI without actually using UI. jQuery
I am learning to use Core Data. I have created a data model etc
I have been learning about TDD (using JUnit) and I have a doubt about
I'm thinking about trying MongoDB to use for storing our stats but have some
I am learning asynchronous programming using C# and I usually use BeginInvoke , but
I am using jQuery's $.ajax method to retrieve some JSON from an API. Each
I am new to taking an object oriented approach with php...actually I have a

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.