如何在C++中将void*指针传递给Lua,并将其传回C++

现在我想将一个void*指针传递给Lua,应该使用userdata吗? 如何做到这一点?

顺便说一句,我使用了luabind,但它无法将void*指针传递给Lua堆栈,这很烦人!你们能帮我吗?

struct Event
{
     A* a;
     B* b;
     ...
};

Event *e;
void* instance = (void*)e;

// param是从Lua脚本传递的参数,param是一个Event对象。我将其转换为void*类型
string Answer(void* param)
{
    WorkEvent *pWorkEvent = static_cast<WorkEvent*>(param);
    ASSERT_RET(pWorkEvent, NULL);

    string call_id = pWorkEvent->GetCallId();
    CCmThreadManager::TType thrd_id =  pWorkEvent->GetHandleThrdID();
    Coroutine *pco    = pWorkEvent->m_pco;
点赞
用户734069
用户734069

在讨论为什么你不应该这样做之前,让我们先回答你的实际问题。

LuaBind是将C++函数和对象绑定到Lua的工具。 void * 既不是函数也不是对象。它确实是一个指向 的指针。因此,对于LuaBind来说,它没有实际含义。因此,您不能直接传递它。

但是,您可以返回一个 luabind::object,该对象可以代表任何Lua值。例如,Lua用户数据。这意味着,您可以从您的 void* 中创建一些轻量级用户数据,将其放入 luabind::object 中,并从与LuaBind注册的函数中返回它。

luabind::object RegisteredFunction(..., lua_State *L)
{
  void *return_value = ...;

  lua_pushlightuserdata(L, return_value);
  luabind::object ret(luabind::from_stack(L, -1));
  lua_pop(L, 1);
  return ret;
}

为了允许Lua返回它以便您可以检索它,只需创建一个以 luabind::object 作为 void* 参数的函数即可:

void OtherRegisteredFunction(..., luabind::object obj, ...)
{
  assert(luabind::type(obj) == LUA_TLIGHTUSERDATA);
  obj.push();
  void *param = lua_touserdata(obj.interpreter(), -1);
  lua_pop(obj.interpreter(), 1);
}

所以这就是如何传递这种类型的数据。现在这里是为什么你不应该这样做。

首先,你的代码是有问题的:

WorkEvent *pWorkEvent = static_cast<WorkEvent*>(param);

假设你的 param 来自这一行:void* instance = (void*)e,C++不能保证这将起作用。如果你将一个对象转换为 void *,C++只提供一个保证,即如果你将它转换回 _完全相同的对象_,它会提供一些有用的东西。

你开始使用一个 Event*,然后转换成了 void *。你唯一 合法 的操作是将其转回 Event*。即使 WorkEventEvent 的派生类,你也不能 直接 将其转换为那个类。您必须首先将其转回 Event*。而且,一旦你有了一个 Event*,你应该使用 dynamic_cast 来进行向下转型。

其次,请停止为此使用 void*。如果您的所有事件都是从 Event* 派生的,则只需传递一个 Event* 并在适当的地方使用 dynamic_cast。如果它们没有,那么您应该 使用 boost::any(因为LuaBind需要Boost,所以显然您已经在使用它了)。你不仅可以将其绑定到LuaBind(因为它是一个实际类型),而且使用起来更加自然。

它具有内置的保护措施,可以解决您的代码之前遇到的问题;如果您在只给出 Event 时尝试将其转换为 WorkEvent,它将抛出异常。

2012-11-20 06:58:56
用户1837970
用户1837970

我们不直接在 Lua 中使用 void*。 在这里,我们使用 C 函数调用 Lua 函数,然后 Lua 函数再调用 C 函数。 在第一个 C 函数中,我们将一个 void* 传递给 Lua 函数,然后 Lua 将 void* 传递给第二个 C 函数。

但是当我们添加默认转换器 void* 时,我们发现无法将 void* 传递给 Lua。

namespace luabind
{
    template <>
    struct default_converter<void*> : native_converter_base<void*>
    {
        static int compute_score(lua_State* L, int index)
        {
            // 此函数将返回 0 或 -1 (int)
            return lua_type(L, index) == LUA_TLIGHTUSERDATA ? 0 : -1;
        }
        void* from(lua_State* L, int index)
        {
            return lua_touserdata(L, index);
        }
        void to(lua_State* L, void* value)
        {
            lua_pushlightuserdata(L, value);
        }
    };

} // namespace luabind
2012-11-20 07:15:02