【问题标题】:lua C api : class accessorslua C api:类访问器
【发布时间】:2016-06-07 14:14:17
【问题描述】:

在这篇文章之后,我已经实现了一个 lua 包装器来使用 lua 中的用户数据访问 C++ 类:http://lua-users.org/wiki/BindingWithMembersAndMethods

我的 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)

除了打印路径变量外,一切正常:

“设置字符串”行来自我在 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 方法和元表的整个部分很长,所以请告诉我你希望我发布什么代码。

【问题讨论】:

    标签: c++ lua


    【解决方案1】:

    我可以看到两个问题。

    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 管理的,并且可以在任何时候被垃圾收集,所以你应该复制它(并且你必须清理之前的值 m_path否则你会得到内存泄漏)。我把细节留给你......

    2. 您发布的 get_string 方法(在您链接的 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 进行垃圾收集),因此您不必考虑这一点。

    【讨论】:

    • 非常感谢先生 =) 它成功了,我明白为什么
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-11
    • 2021-05-04
    • 1970-01-01
    相关资源
    最近更新 更多