macroland
macroland

Reputation: 1035

Lua C++ userdata

I am trying to access the type of a userdata so that I can process it accordingly. Imagine I have a class named as Foo:

class Foo:public CObject
{
 public:
 Foo():CObject(){}
 int type() {return 1;}
}

class CObject
{
 public:
 virtual int type(void)=0;
}

The rationale is that every class extending the CObject has a type that must be made known by an integer number (later on an enum). The class Foo is bind to lua using luaWwrapper (//https://bitbucket.org/alexames/luawrapper/src/fd9c4fdbf4b25034e3b8475a2c8da66b7caab427?at=default).

  Foo* Foo_new(lua_State* L)
  {
    Foo* f=new Foo();
    lua_newuserdata(L,sizeof(f));
    std::cout<<"f="<<f;
    return f;
  }

In Lua user calls this as:

f=Foo.new() 
print(f)

Now I have a C++ function, say print:

int lua_print(lua_State* L)
{
   void *ud = luaL_checkudata(L, 1, "Foo"); //ud is not zero
    std::cout<<"ud="<<ud;
    CObject* obj=(CObject*)ud;  //Casting to CObject
   int objtype=obj->type();   //program CRASHES here

}

I have seen that the program crashes cause the memory addresses of Foo and ud are not the same. I assume ud refers to the memory of stack which contains the memory adress of Foo. How can I access stack's memory address or the preferred memory address of Foo?

Upvotes: 1

Views: 883

Answers (2)

Alex
Alex

Reputation: 15343

Foo_new should just return the pointer to the object.

In other words, your Foo_new would look like this:

Foo* Foo_new(lua_State* L)
{
  return new Foo();
}

However, if you have no special initialization you need to do, you don't even need to write this function. This function is supplied for you by magical templates if you don't write one yourself.

When you want to get your Foo object from the Lua state, you do this:

int lua_print(lua_State* L)
{
   Foo *ud = luaW_to<Foo>(L, 1); //ud is not zero
   std::cout<<"ud="<<ud;
   CObject* obj=(CObject*)ud;
   int objtype=obj->type();
}

If CObject is registered with LuaWrapper too, you don't even need to do the manual cast. You can just do luaW_to<CObject>(L, 1);

Upvotes: 0

roeland
roeland

Reputation: 5751

You have to use placement new to initialize the object in the memory returned by lua_newuserdata.

Something in the lines of

void *ud = lua_newuserdata(L,sizeof(Foo));
new (ud) Foo();

Upvotes: 1

Related Questions