Кастинг между пустотой * и указателем на функцию членства

Вот то, как я недавно сделал это. Не прекрасный семантически, но сделали задание.

<div class="container" style="position: relative">
<img style="z-index: 32; left: 8px; position: relative;" alt="bottom image" src="images/bottom-image.jpg">
<div style="z-index: 100; left: 72px; position: absolute; top: 39px">
<img alt="top image" src="images/top-image.jpg"></div></div>
13
задан Jarod42 5 September 2018 в 14:52
поделиться

2 ответа

Вы не можете привести указатель на член к void * или к любому другому «обычному» типу указателя. Указатели на члены не являются адресами, как обычные указатели. Что вам, скорее всего, нужно будет сделать, так это обернуть вашу функцию-член в обычную функцию. В C ++ FAQ Lite это подробно объясняется. Основная проблема заключается в том, что данные, необходимые для реализации указателя на член, - это не просто адрес, и на самом деле сильно различается в зависимости от реализации компилятора.

Я предполагаю, что вы контролируете, что данные пользователя lua_touserdata возвращаются. Это не может быть указатель на член, поскольку нет законного способа вернуть эту информацию. Но у вас есть и другие варианты:

  • Самый простой вариант - обернуть вашу функцию-член в бесплатную функцию и вернуть ее. Эта бесплатная функция должна принимать объект в качестве первого аргумента. См. Пример кода ниже.

  • Используйте технику, аналогичную методу mem_fun Boost.Bind, чтобы вернуть объект функции, для которого можно создать шаблон. Я не думаю, что это проще, но это позволило бы вам связать состояние more с функцией return, если вам нужно.

Вот перезапись вашей функции с использованием первого способа:

template <class T>
int call_int_function(lua_State *L) 
{
    void (*method)(T*, int, int) = reinterpret_cast<void (*)(T*, int, int)>(lua_touserdata(L, lua_upvalueindex(1)));
    T *obj = reinterpret_cast<T *>(lua_touserdata(L, 1));

   method(obj, lua_tointeger(L, 2), lua_tointeger(L, 3));
   return 0;
}
21
ответ дан 1 December 2019 в 19:40
поделиться

В качестве обходного пути, учитывая ограничения преобразования указателя на функцию-член в void * , вы можете заключить указатель функции в небольшую структуру, выделенную в куче, и поместить указатель на эту структуру в ваших пользовательских данных Lua:

template <typename T>
struct LuaUserData {
    typename void (T::*MemberProc)(int, int);

    explicit LuaUserData(MemberProc proc) :
        mProc(proc)
    { }

    MemberProc mProc;
};

LuaObject<Foo> lobj = registerObject(L, "foo", fooObject);
LuaUserData<Foo>* lobj_data = new LuaUserData<Foo>(&Foo::bar);

lobj.addField(L, "bar", lobj_data);

// ...

template <class T>
int call_int_function(lua_State *L) 
{
    typedef LuaUserData<T>                       LuaUserDataType;
    typedef typename LuaUserDataType::MemberProc ProcType;

    // this next line is problematic
    LuaUserDataType* data =
        reinterpret_cast<LuaUserDataType*>(lua_touserdata(L, lua_upvalueindex(1)));
    T *obj = reinterpret_cast<T *>(lua_touserdata(L, 1));

    (obj->*(data.mMemberProc))(lua_tointeger(L, 2), lua_tointeger(L, 3));
    return 0;
}

Я не разбираюсь в Lua, поэтому я, вероятно, что-то пропустил в приведенном выше примере. Имейте в виду, что если вы пойдете по этому пути, вам придется управлять распределением LuaUserData.

1
ответ дан 1 December 2019 в 19:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: