简体   繁体   中英

Can't call member function from c++/lua function

I've been trying something with lua and c++ for a while now, and all the "easy" functions work, ie can call a c++ function from lua and the other way around, however I have 1 major problem.

its a tiny game/simulator in the making and I wanted to use lua, ode and make my own tiny interface (not a direct one like LuaOde). My code structure is as follows

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

now I of course want to talk to Physics from LuaAddons. so in LuaAddons.cpp I have:

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;
}

That way I can simply call setWorldGravity(1, 2, 3) in my .lua file and the above function is called accordingly with the correct parameters passed through.

Here is where the problem is however. Inside that int setWorldGravity I want to make a call to the physics part of the application and call the corrosponding function that has the ODE call to set the gravity.

So in Physics.h I have:

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

which calls the correct ODE function with those parameters:

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

Where world_ is the world created when it was first initiated by the main class.

However since the int setWorldGravity(lua_State* L) in LuaAddons is not a member of that class (ie not defined in LuaAddons.h, and if it would be it would have had to be static) I can't for the life of me figure out how to approach the singular instanced Physics(); from within the function itself. Obviously I can't just let LuaAddons create a new instance of Physics since that would not have the same world.

What i've tried is:

l = new LuaAddons(p);

where (in LuaAddons.h)

LuaAddons(Physics* p);

and (in LuaAddons.cpp)

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

However when I try to add

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

It won't work because (big surprise) the function does not know about phys_.

I've also tried using the Lunar.h library. With this I could reshape the lua function to a member function, have it declared in the .h and actually call phys_->stuff. However the library also forces you to make a new instance of the caller (mind boggles) in the .lua in order to call its members:

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

However this way the link to the Physics part is gone as the default constructor does not get the pointer passed to it. As soon as this call goes through the objects and reaches the part where the it is applied to ODE it simply crashes (assuming null pointer or.. something pointer wrongy :P)

I would venture a guess that I'd be almost forced to pass the Physics pointer through the lua file if I actually wanted to make sure that the exact same physics world is operated on. But I've not the slightest idea how.

I'm sorry for the long read but I'd rather be thorough then leave out vital details.

Any help/thoughts would be tremendously appreciated.

In C++, member functions are essentially functions with a hidden parameter. You write:

class Foo {
    const int bar_;

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

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

But, effectively, you actually get:

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

In C++, this hidden parameter is called the this pointer (in Python it's self , other languages have other names).

It sounds like what you want is a C-like function that will call the C++ member function, passing that hidden parameter. The easiest solution is to write a C function that takes all the parameters that the member function takes, plus an additional parameter: the object to call the function on:

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

There are other techniques (pointer to member function comes to mind), but this should get you started.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM