Lua对象内省

我使用[lualite](http://code.google.com/p/lualite/)在lua中包装了以下对象:

class SpriteComponent : public Component
{
public:
    SpriteComponent();

    std::string name() const;
    std::string textureId() const;
    void setTextureId(const std::string& id);
    int spriteCoordX() const;
    void setSpriteCoordX(int value);
    int spriteCoordY() const;
    void setSpriteCoordY(int value);
};

绑定代码:

module(L,
    class_<SpriteComponent>("SpriteComponent")
        .constructor("new")
        .def("name", &SpriteComponent::name)
        .property("textureId",
            &SpriteComponent::textureId, &SpriteComponent::setTextureId)
        .property("spriteCoordX",
            &SpriteComponent::spriteCoordX, &SpriteComponent::setSpriteCoordX)
        .property("spriteCoordY",
            &SpriteComponent::spriteCoordY, &SpriteComponent::setSpriteCoordY)
);

是否有一种方法(无论是在lua端还是C++端)来获取属性列表?如果我在生成的表中列出键值对,我只会得到name__instance

local o = SpriteComponent.new()
for key,value in pairs(o) do
    print("found member " .. key);
end

我甚至尝试了一些[这些](http://lua-users.org/wiki/TableSerialization)表打印机,但没有运气。

点赞
用户2633423
用户2633423

如果你能够容忍在 Lua 代码中列出属性名,那么这可能是一个解决方案:

local GetPropertyList
do -- 使 `property_names` 对 `GetPropertyList` 私有化
    property_names = {
        ["SpriteComponent"] = { "textureId", "spriteCoordX", "spriteCoordY" },
        -- 其他组件的属性名,例如:
        ["AnotherComponentName"] = { "propName1", "propName2" },
    }
    function GetPropertyList( object )  --[[local]]
        local component_name = object:name()
        local prop_names = property_names[component_name]
        if not prop_names then
            error( "不支持的组件" )
        end
        local res = {}
        for _, p_name in ipairs( prop_names ) do
            local p_val = object[p_name]
            res[ #res + 1 ] = p_val
            -- 或者如果你想要一个 key-value 映射:
            -- res[p_name] = p_val
        end
        return res
    end  -- function
end  -- do

for k, v in pairs( GetPropertyList(o) ) do
    print( k, v )
end
2013-10-06 12:21:22
用户1095108
用户1095108

我是 lualite 的作者。我编写了这个库是为了让它简洁快速,并没有考虑到需要反射的情况 :) 无论如何,您正在寻找的可以在这两个静态成员中找到:

static ::std::unordered_map<char const*, detail::map_member_info_type,
  detail::unordered_hash, detail::unordered_eq> getters_;
static ::std::unordered_map<char const*, detail::map_member_info_type,
  detail::unordered_hash, detail::unordered_eq> setters_;

char const* 是属性名称,值是 map_member_info_type,它实际上是两个指针,一个指向 lualite 存根,另一个指向 C++ 成员函数。

struct map_member_info_type
{
  lua_CFunction callback;

  member_func_type func;
};

如果您愿意,我可以将这两个成员设为公共成员。属性的工作方式如下:

默认的 getter 通常在包装类的实例表中设置:

lua_pushcclosure(L, default_getter<C>, 2);

rawsetfield(L, -2, "__index");

这指向默认的 getter:

template <class C>
int default_getter(lua_State* const L)
{
  assert(2 == lua_gettop(L));
  auto const i(lualite::class_<C>::getters_.find(lua_tostring(L, 2)));

  return lualite::class_<C>::getters_.end() == i
    ? 0
    : (lua_pushlightuserdata(L, &i->second.func),
      lua_replace(L, lua_upvalueindex(2)),
      (i->second.callback)(L));
}

它查找属性名称(在堆栈上),这可以是任何东西,如果没有找到名称,则返回 0,否则将调用 lualite 存根所做的成员函数,然后处理参数和返回值。

2013-11-04 08:17:17