2011-01-20 7 views
3

J'ai essayé quelque chose avec lua et C++ depuis un moment maintenant, et toutes les fonctions "faciles" fonctionnent, c.-à-d. Peuvent appeler une fonction C++ de lua et inversement autour, mais j'ai un problème majeur.Impossible d'appeler la fonction membre de la fonction C++/lua

C'est un minuscule jeu/simulateur en devenir et je voulais utiliser lua, ode et créer ma propre petite interface (pas directe comme LuaOde). Ma structure de code est le suivant

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

maintenant je veux bien sûr parler de physique de LuaAddons. donc dans LuaAddons.cpp J'ai:

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

De cette façon, je peux simplement appeler setWorldGravity(1, 2, 3) dans mon fichier .lua et la fonction ci-dessus est appelé en conséquence avec les bons paramètres passés par.

Voici où le problème est cependant. A l'intérieur de ce int setWorldGravity je veux faire un appel à la partie physique de l'application et appeler la fonction corrosponding qui a l'appel ODE pour définir la gravité.

Donc Physics.h j'ai:

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

qui appelle la fonction ODE correcte avec ces paramètres:

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

world_ est le monde créé quand il a été initié par le principal classe.

Cependant, comme le int setWorldGravity(lua_State* L) dans LuaAddons n'est pas un membre de cette classe (c'est-à-dire non défini dans LuaAddons.h, et si cela devait être il aurait dû être statique) Je ne peux pas pour la vie de moi comprendre comment approcher la physique instanciée singulière(); à l'intérieur de la fonction elle-même. Évidemment, je ne peux pas laisser LuaAddons créer une nouvelle instance de Physics puisque cela n'aurait pas le même monde.

Ce que j'ai essayé est:

l = new LuaAddons(p); 

où (en LuaAddons.h)

LuaAddons(Physics* p); 

et (en LuaAddons.cpp)

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

Cependant lorsque je tente ajouter

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

Cela ne fonctionnera pas car (grande surprise) la fonction ne connaît pas phys_.

J'ai également essayé d'utiliser la bibliothèque Lunar.h. Avec ceci je pourrais remodeler la fonction de lua à une fonction de membre, l'avoir déclarée dans le .h et appeler réellement phys _-> substance. Cependant, la bibliothèque vous oblige également à faire une nouvelle instance de l'appelant (l'esprit rechigne) dans le .lua pour appeler ses membres:

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

Cependant cette façon, le lien vers la partie physique est disparu par défaut Le constructeur ne reçoit pas le pointeur.Dès que cet appel passe par les objets et atteint la partie où il est appliqué à ODE il se bloque simplement (en supposant null pointeur ou .. quelque chose pointeur mal: P)

Je me hasarderais à deviner que je serais presque forcé de passer le pointeur de la physique à travers le fichier lua si je voulais vraiment m'assurer que le même monde physique est opéré. Mais je n'ai pas la moindre idée de comment.

Je suis désolé pour la lecture longue mais je préfère être minutieux alors omettre les détails vitaux.

Toute aide/pensée serait grandement appréciée.

Répondre

3

En C++, les fonctions membres sont essentiellement des fonctions avec un paramètre masqué. Vous écrivez:

class Foo { 
    const int bar_; 

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

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

Mais, effectivement, vous obtenez en fait:

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

En C++, ce paramètre caché est appelé le pointeur this (en Python, il est self, d'autres langues ont d'autres noms).

Il semble que ce que vous voulez est une fonction de type C qui appellera la fonction membre C++, passant ce paramètre caché. La solution la plus simple est d'écrire une fonction C qui prend tous les paramètres que la fonction de membre prend, plus un paramètre supplémentaire: l'objet pour appeler la fonction sur:

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

Il existe d'autres techniques (pointeur vers une fonction membre vient à l'esprit), mais cela devrait vous aider à démarrer.

Questions connexes