2

Lua にポインターを渡したいのですが、void*userdata を使用しますか? これを行う方法?

ところで、私は luabind を使用しましたが、void*Lua スタックへのポインターを渡すことができません。これは面倒です! 皆さん、私を助けてくれませんか?

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

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


// param is a parameter that is passed from Lua script. param is a Event object. And I cast it into a void* type
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;
4

2 に答える 2

6

なぜこれを行うべきではないのかを説明する前に、実際の質問に答えましょう。

LuaBindは、C++関数とオブジェクトをLuaにバインドするためのツールです。Avoid*は関数でもオブジェクトでもありません。それは、文字通り、何もないことへのポインタです。そのため、LuaBindにとって実際の意味はありません。したがって、直接渡すことはできません。

ただし、任意のLua値を表すことができるを返すことができます。luabind::objectたとえば、Luaのユーザーデータ。つまり、から簡単なユーザーデータを作成しvoid*、に貼り付けて、luabind::objectLuaBindに登録した関数から返すことができます。

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*操作は、それをにキャストバックすることです。WorkEventの派生クラスであっても、そのクラスに直接Eventキャストすることはできません。あなたはそれを最初に戻さなければなりません。また、を取得したら、を使用してダウンキャストを実行する必要があります。Event*dynamic_castEvent*

次に、void*このためのsの使用を停止します。すべてのイベントがから派生している場合はEvent*、を渡して、必要に応じEvent*て使用dynamic_castします。そうでない場合は、使用boost::anyする必要があります(LuaBindにはBoostが必要なので、明らかにすでに使用しています)。これをLuaBindにバインドできるようになるだけでなく(実際のタイプであるため)、操作するのがはるかに自然になります。

また、コードが以前に抱えていた問題からの保護が組み込まれています。WorkEventが与えられたときにキャストしようとするとEvent、例外がスローされます。

于 2012-11-20T06:58:56.963 に答える
2

lua では void* を直接使用しません。ここでは、c 関数を使用して lua 関数を呼び出し、次に lua 関数を使用して最初の c で c 関数を呼び出し、void* を lua 関数に渡し、次に lua が void* を 2 番目の c 関数に渡します。

しかし、default_converter void* を追加すると、lua に void* を渡すことができないことがわかりました。

namespace luabind
{
    template <>
    struct default_converter<void*> : native_converter_base<void*>
    {
        static int compute_score(lua_State * L, int index)
        {
            // this function will return 0 or -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-20T07:15:02.323 に答える