2016-06-07 65 views
1

我已經實現了LUA包裝訪問使用用戶數據C++類在Lua本文以下內容:http://lua-users.org/wiki/BindingWithMembersAndMethodsLUA C API:類訪問器

我的C++類如下所示:

class GameObject 
{ 
public: 
    GameObject(); 
    ~GameObject(); 

    int    m_id; 
    float   m_scale; 
    const char*  m_path; 
}; 

到目前爲止我可以在Lua做到這一點:

gameObject = GameObject.new() 
gameObject.path = "test" 
gameObject.scale = 2 
local path = gameObject.path 
local scale = gameObject.scale 
print(scale) 
print(path) 

,一切工作正常打印路徑變量時除外:

console output

「設置串」線來自調試我把setter函數:

int LuaGameObjectManager::set_string (lua_State *L, void *v) 
{ 
    v = (void*)luaL_checkstring(L, 3); 
    std::cout << "set string : " << (char*) v << std::endl; 
    return 0; 
} 

所以我想我設置正確的值,必須發生問題時,得到它與此getter函數:

int LuaGameObjectManager::get_string (lua_State *L, void *v) 
{ 
    char * tmp = (char*)v; 
    lua_pushstring(L, tmp); 
    return 1; 
} 

這也是我如何定義我的方法和元表:

static const luaL_Reg methodsArray[] = { 
    {"new",  New}, 
    {"load",  load}, 
    {0,0} 
}; 

static const luaL_Reg metaArray[] = { 
    {"__gc",  gc}, 
    {"__tostring", toString}, 
    {0, 0} 
}; 

static LuaManager::Xet_reg_pre gettersArray[] = { 
    {"scale",  get_int, offsetof(GameObject, m_scale) }, 
    {"path",  get_string, offsetof(GameObject, m_path) }, 
    {0,0} 
}; 

static LuaManager::Xet_reg_pre settersArray[] = { 
    {"scale",  set_int, offsetof(GameObject, m_scale) }, 
    {"path",  set_string, offsetof(GameObject, m_path) }, 
    {0,0} 
}; 

那麼,有沒有人有一個想法,爲什麼我打印一些奇怪的值?這是一個編碼問題? 我知道你們需要更多的代碼來理解我的問題,並且幫助我,但是註冊lua方法和metatable的整個過程非常漫長,所以只需告訴我你想要發佈的代碼。

回答

2

我可以看到兩個問題。

  1. 賦值給函數內的(原始)局部變量對外界沒有影響。

    int LuaGameObjectManager::set_string (lua_State *L, void *v) 
    { 
        v = (void*)luaL_checkstring(L, 3); 
    

    v這裏是一個局部變量,因此這並沒有set_string方法之外任何改變。你的對象的內存佈局是這樣的:

       v 
           \ 
    | int | float |pointer| 
            \ 
            |c|c|c|c|c|... 
    

    所以,你可能希望類似

    *((char**)v) = luaL_checkstring(L, 3); 
    

    的東西,但是要注意的是,字符串luaL_checkstring回報是Lua的管理,並且可以garbage-在任何時候收集,所以你應該複製它(你必須清理之前的值m_path或者你會得到一個內存泄漏)。我會把細節留給你...

  2. 你發佈的方法(並且在你鏈接的wiki文章中使用的方法)假定它正在處理內聯字符數組。

       v 
           \ 
    | int | float |c|c|c|c|c|... 
    

    您的情況與使用指向字符數組的第一個元素的指針不同(請參見上文)。一個適當的實施將看起來像:

    int LuaGameObjectManager::get_string (lua_State *L, void *v) 
    { 
        lua_pushstring(L, *((char**)v)); 
        return 1; 
    } 
    

    在這種情況下lua_pushstring已經讓你的副本(這將是垃圾收集Lua的最終),所以你不必考慮這個問題。

+0

謝謝你很多先生=)它的工作,我明白了爲什麼 – Narthe