2015-06-21 120 views
1

我試圖訪問一個userdata的類型,以便我可以相應地處理它。想象我有一個命名爲Foo類:Lua C++ userdata

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

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

的理由是,延伸的CObject的每一個類具有必須由通過的整數已知的類型(以後枚舉)。 Foo類使用luaWwrapper綁定到lua(// 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; 
    } 

在Lua的用戶稱這爲:

f=Foo.new() 
print(f) 

現在我有一個C++函數,比如說打印:

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 

}

我已經看到,程序崩潰導致Fooud的內存地址不一樣。 I 假定ud是指包含Foo的存儲器地址的堆棧的存儲器。如何訪問堆棧的內存地址或Foo的首選內存地址?

回答

1

您必須使用placement new來初始化由lua_newuserdata返回的內存中的對象

在東西線的

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

Foo_new應該把指針剛剛回歸的對象。

換句話說,你Foo_new應該是這樣的:

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

但是,如果你有你需要做的沒有特殊的初始化,你甚至不需要寫這個功能。如果你自己沒有寫一個神奇的模板,這個功能就是爲你提供的。

當你想從Lua的狀態讓你Foo對象,你這樣做:

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(); 
} 

如果CObject與LuaWrapper過註冊,你甚至都不需要做人工投。你可以做luaW_to<CObject>(L, 1);