3 Stimmen

Kann Mitgliedsfunktion nicht von C++/Lua-Funktion aufrufen

Ich habe versucht, etwas mit Lua und C++ für eine Weile jetzt, und alle "einfachen" Funktionen funktionieren, dh kann eine C++-Funktion von Lua und umgekehrt aufrufen, jedoch habe ich 1 großes Problem.

Es ist ein kleines Spiel/Simulator in der Herstellung und ich wollte Lua, Ode verwenden und meine eigene kleine Schnittstelle (nicht eine direkte wie LuaOde) machen. Meine Code-Struktur ist wie folgt

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

jetzt möchte ich natürlich mit Physics von LuaAddons sprechen. also in LuaAddons.cpp habe ich:

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

Auf diese Weise kann ich einfach aufrufen setWorldGravity(1, 2, 3) in meiner .lua-Datei und die obige Funktion wird entsprechend aufgerufen, wobei die richtigen Parameter übergeben werden.

Aber genau hier liegt das Problem. Innerhalb dieser int setWorldGravity Ich möchte einen Aufruf an den Physik-Teil der Anwendung machen und die entsprechende Funktion aufrufen, die den ODE-Aufruf hat, um die Schwerkraft einzustellen.

In Physics.h habe ich also:

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

der die richtige ODE-Funktion mit diesen Parametern aufruft:

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

Dónde world_ ist die Welt, die erstellt wurde, als sie zum ersten Mal von der Hauptklasse initiiert wurde.

Da jedoch die int setWorldGravity(lua_State* L) in LuaAddons ist kein Mitglied dieser Klasse (d.h. nicht in LuaAddons.h definiert, und wenn sie es wäre, müsste sie statisch sein). Ich kann beim besten Willen nicht herausfinden, wie man sich der einzelnen instanzierten Physics(); aus der Funktion selbst nähert. Offensichtlich kann ich nicht einfach LuaAddons eine neue Instanz von Physics erstellen lassen, da dies nicht die gleiche Welt haben würde.

Was ich versucht habe, ist:

l = new LuaAddons(p);

wo (in LuaAddons.h)

LuaAddons(Physics* p);

und (in LuaAddons.cpp)

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

Wenn ich jedoch versuche, die

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

Es wird nicht funktionieren, weil (große Überraschung) die Funktion nicht über phys_ weiß.

Ich habe auch versucht, die Bibliothek Lunar.h zu verwenden. Damit konnte ich die Lua-Funktion zu einer Member-Funktion umgestalten, sie in der .h deklarieren lassen und tatsächlich phys_->stuff aufrufen. Die Bibliothek zwingt einen aber auch dazu, eine neue Instanz des Aufrufers in der .lua zu erstellen, um dessen Mitglieder aufrufen zu können:

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

Auf diese Weise ist jedoch die Verbindung zum Physics-Teil nicht mehr vorhanden, da der Standardkonstruktor den Zeiger nicht übergeben bekommt. Sobald dieser Aufruf durch die Objekte geht und den Teil erreicht, wo er auf ODE angewendet wird, stürzt er einfach ab (unter der Annahme, dass der Zeiger Null ist oder etwas nicht stimmt :P)

Ich würde vermuten, dass ich fast gezwungen wäre, den Physik-Zeiger über die Lua-Datei zu übergeben, wenn ich tatsächlich sicherstellen wollte, dass genau dieselbe Physik-Welt bedient wird. Aber ich habe nicht die geringste Ahnung, wie.

Es tut mir leid, dass die Lektüre so lang ist, aber ich bin lieber gründlich, als wichtige Details auszulassen.

Jede Hilfe/jeder Gedanke wäre mir sehr willkommen.

3voto

Max Lybbert Punkte 19181

In C++ sind Mitgliedsfunktionen im Wesentlichen Funktionen mit einem versteckten Parameter. Sie schreiben:

class Foo {
    const int bar_;

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

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

Aber in der Tat, Sie bekommen:

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

In C++ wird dieser versteckte Parameter als this Zeiger (in Python ist es self , andere Sprachen haben andere Namen).

Es klingt so, als ob Sie eine C-ähnliche Funktion benötigen, die die C++-Mitgliedsfunktion aufruft und den versteckten Parameter übergibt. Die einfachste Lösung besteht darin, eine C-Funktion zu schreiben, die alle Parameter der Mitgliedsfunktion sowie einen zusätzlichen Parameter benötigt: das Objekt, mit dem die Funktion aufgerufen werden soll:

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

Es gibt noch andere Techniken (z.B. Pointer to Member Function), aber das sollte für den Anfang genügen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X