Не могу вызвать функцию-член из функции c ++ / lua - PullRequest
3 голосов
/ 20 января 2011

Я уже некоторое время пытаюсь что-то с lua и c ++, и все «легкие» функции работают, то есть могут вызывать функцию c ++ из lua и наоборот, однако у меня есть одна серьезная проблема.

это крошечная игра / симулятор, и я хотел использовать lua, ode и сделать свой собственный крошечный интерфейс (не прямой, как LuaOde). Моя структура кода выглядит следующим образом

main class //creates instances of Visual, Physics and LuaAddons
  v = new Visual();
  p = new Physics();
  l = new LuaAddons();

Теперь я, конечно, хочу поговорить с физиками из LuaAddons. поэтому в LuaAddons.cpp у меня есть:

int setWorldGravity(lua_State* L){
  float x = luaL_checknumber(L, 1);
  float y = luaL_checknumber(L, 2);
  float z = luaL_checknumber(L, 3);
  //Here I need to somehow talk to p (Physics())     
  return 0;
}

Таким образом, я могу просто вызвать setWorldGravity(1, 2, 3) в моем файле .lua, и вышеуказанная функция вызывается соответственно с правильными параметрами, переданными через.

Здесь проблема, однако. Внутри этого int setWorldGravity я хочу позвонить в физическую часть приложения и вызвать соответствующую функцию, которая имеет вызов ODE для установки гравитации.

Так в Physics.h у меня есть:

void setWorldGravity(float x, float y, float z);

, которая вызывает правильную функцию ODE с этими параметрами:

void Physics::setWorldGravity( float x, float y, float z ){
  dWorldSetGravity (world_, x, y, z);  
} 

Где world_ - мир, созданный, когда он был впервые инициирован главным классом.

Однако, поскольку int setWorldGravity(lua_State* L) в LuaAddons не является членом этого класса (то есть не определено в LuaAddons.h, и если бы это было так, оно должно было бы быть статичным). узнать, как приблизиться к единственному экземпляру Physics (); изнутри самой функции. Очевидно, я не могу просто позволить LuaAddons создать новый экземпляр Physics, поскольку у него не будет того же мира.

То, что я пробовал, это:

l = new LuaAddons(p);

где (в LuaAddons.h)

LuaAddons(Physics* p);

и (в LuaAddons.cpp)

LuaAddons(Physics* p){
  phys_ = p; // where phys_ is a private member of LuaAddons.h
}

Однако, когда я пытаюсь добавить

phys_->setWorldGravity(x, y, z); // error C2065: 'phys_' : undeclared identifier

Это не сработает, потому что (большой сюрприз) функция не знает о физ. _.

Я также пытался использовать библиотеку Lunar.h. При этом я мог бы преобразовать функцию lua в функцию-член, объявить ее в .h и фактически вызвать phys _-> stuff. Однако библиотека также вынуждает вас сделать новый экземпляр вызывающей стороны (ошеломляющие мысли) в .lua для вызова ее членов:

la_ = LuaAddons()
la_:setWorldGravity(1, 2, 3)

Однако при этом ссылка на часть Physics исчезает, так как конструктор по умолчанию не передает указатель на него. Как только этот вызов проходит через объекты и достигает части, где он применяется к ODE, он просто падает (при условии, что нулевой указатель или .. что-то неверно указывает указатель: P)

Я бы рискнул предположить, что я был бы почти вынужден пропустить указатель Physics через файл lua, если бы на самом деле хотел убедиться, что работает тот же самый физический мир. Но я понятия не имею, как.

Прошу прощения за долгое прочтение, но я предпочел бы быть внимательным, а затем опустить важные детали.

Буду очень признателен за любую помощь / мысли.

1 Ответ

3 голосов
/ 20 января 2011

В C ++ функции-члены по сути являются функциями со скрытым параметром. Вы пишете:

class Foo {
    const int bar_;

    public:
    Foo(int b) : bar_ { }
    int get_bar()
    {
        return bar_;
    }
};

Foo f(5);
f.get_bar();

Но фактически вы получаете:

Foo f = Foo_constructor(5);
Foo_get_bar(f);

В C ++ этот скрытый параметр называется указателем this (в Python это self, другие языки имеют другие имена).

Звучит так, как будто вам нужна C-подобная функция, которая будет вызывать функцию-член C ++, передавая этот скрытый параметр. Самое простое решение - написать функцию C, которая принимает все параметры, которые принимает функция-член, плюс дополнительный параметр: объект, для которого вызывается функция:

void setWorldGravityWrapper(Physics* p, int x, int y, int z)
{
    return p->setWorldGravity(x, y, z);
}

Существуют и другие методы (на ум приходит указатель на функцию-член), но с этого следует начать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...