问题
I'm using Luabind.
My title might be kind of unclear, I will try the best i can to explain what i want to ask.
My question is:
How do i directly tall C++ object's method that can access the object's values(especially pointers) rather then creating Another object in Luabind.
If you don't know what I'm asking, You can continue reading.
For example, i have three classes: Main
, Test_Stage
, Test_Class
the Lua is created only in Test_class
.
I have a variable x
,created just for testing purpose. It is passed all the way from the Main
to Test_Stage
to Test_Class
by their constructor. So that both Test_Class
and Test_Stage
have a global value which I'll need when I'm actually making the game.
More important thing is that Test_Class
holds a pointer of Test_Stage
, so that i can do such things as create_a_bullet
or create_damage
.
Learned from this Tutorial, I had tried to make The luaobject
created in Test_Class
call the method shoot_a_bullet
which will tall 'Test_Stage' object to print "Runned " << 'the global value'. And without a syntax error in C++, IT didn't print anything. How can i fix this?
Codes are here(actually i had trouble working with forward including using class, so "Runned" << x is in Test_Class
. At least I can test if it will read the global value had passed here.)
Edit: Just after few hours of doing nothing, I had though about another solution. Is there a way i can pass the pointer that can be used in the object that is created in lua, or maybe used in constructer?
Codes(you might considering skip the main and Test_Stage if you come for answering the question :
The main file start the program:
#include <iostream>
#include "test_stage.h"
using namespace std;
int x;
int main() {
cin >> x;
Test_Stage stage = Test_Stage(x);
}
And the Header of Test_Stage
:
#ifndef TEST_STAGE_H
#define TEST_STAGE_H
#include <iostream>
class Test_Class;// to avoid circular include error, i used forward referancing
// i will include the file in the CPP file
// a class Test_Class which define the class is enough in header
using namespace std;
class Test_Stage
{
public:
int x;
Test_Stage(int num);
void create_bullet(int damage, string name, int x); /*This is currently useless
before i have understand how to include each other using foward referance*/
void create_class(int num);
Test_Class t_class;
~Test_Stage();
private:
};
#endif
The cpp file of Test_Stage:
#include"test_stage.h"
#include "test_class.h"// and as you see i included both files(i just learned it few secs ago)
Test_Stage::Test_Stage()
{
}
Test_Stage::Test_Stage(int num)
{
create_class(num);
}
void Test_Stage::create_bullet(int damage, string name, int x)
{
cout << "created damage: " << damage << "to" << x ;
}
void Test_Stage::create_class(int num)
{
Test_Class t_class = Test_Class(num, this);
}
Test_Stage::~Test_Stage()
{
}
The header of Test_Class:
#ifndef TEST_CLASS_H
#define TEST_CLASS_H
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include ".\luabind\luabind.hpp"
#include <iostream>
using namespace std;
class Test_Stage;
class Test_Class
{
public:
int x;
Test_Class();
Test_Class(int num, Test_Stage* stage);
void shoot_a_bullet(Test_Class* o, int damage);
Test_Stage *stage;
~Test_Class();
private:
};
#endif TEST_CLASS_H
And finally the cpp of Test_Class(causing me lot's trouble):
#include "test_class.h"
#include"test_stage.h"
void Test_Class::shoot_a_bullet(Test_Class* o, int damage)
{
cout << "Runned";
stage->create_bullet(damage, "wowo", x);
}
Test_Class::Test_Class()
{
}
Test_Class::Test_Class(int num, Test_Stage* stg)
{
stage = stg;
x = num;
// Create a new lua state
lua_State *myLuaState = luaL_newstate();
// Connect LuaBind to this lua state
luabind::open(myLuaState);
luaL_openlibs(myLuaState);
luabind::module(myLuaState)[
luabind::class_<Test_Class>("Test_Class")
.def("shoot_a_bullet", &Test_Class::shoot_a_bullet)
];
/*followed the tutorial codes
class_<A>("A")
.def("plus", &plus)*/
cout << "im here";//just to check how far did the program go
luaL_dostring(
myLuaState,
"shoot_a_bullet(134)\n"
);
cout << "I passed it";
cin.get();
cin.get();//To pause the program before it closes
// if you have the time, can you also explain
// why do i need two cin.get() to pause the program.
}
Test_Class::~Test_Class()
{
}
回答1:
After tons, and tons of researches, I had finally figured out an solution although I'm not sure about how efficient it is, it's actually working the way i wanted it to be.
So the final solution is, to register an intptr_t
converted from the pointer i needed to lua,(for more information about intptr_t
, click here(mainly for safety reason, you can see it as a kind of int design just for pointers)) and pass it to the static function when I'm using it
Here is the Code after modification:
In Test_Class.cpp
, after:
luabind::module(myLuaState)[
.def("shoot_a_bullet", &shoot_a_bullet)
];// since the functions are static now it will not need the namespace
I had registered the intptr_t
version of pointer:
//first convert pointer to intptr_t
intptr_t stage = (intptr_t)stg;//stg is the pointer
//then register it to lua
//if you try to register a pointer it will give you runtime error
luabind::globals(myLuaState)["stage"] = stage;
We also need to change the function a little bit:
First, we need to make the function static, so in the header file:
//change the line defined the function to
void static shoot_a_bullet(intptr_t stg, int damage);
Now we have to do things with the function it self:
void Test_Class::shoot_a_bullet(intptr_t stg, int damage)
{
//we need to convert it back to pointer first, so
Test_Stage* stage = (Test_Stage*)stg;//this is the part I'm not sure about efficiency
stage->create_bullet(damage, "wowo");
}
So now the Code with lua will be really simple: shoot_a_bullet(stage, 134);
We are done! Life is good! This stuff has costed me 3 week.
In chance you might not understanding what i said, here is the complete test code i had writen:
main
.cpp:
#include <iostream>
#include "test_stage.h"
using namespace std;
int x;
int main() {
cin >> x;
cin.get();// clean the \n(when you press enter) after the number
Test_Stage stage = Test_Stage(x);
}
Test_Stage
.h:
class Test_Class;
#ifndef TEST_STAGE_H
#define TEST_STAGE_H
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include ".\luabind\luabind.hpp"
#include <iostream>
#include "test_class.h"
using namespace std;
class Test_Stage
{
public:
int x;
Test_Stage();
Test_Stage(int num);
void create_bullet(int damage, string name); /*This is currently useless
before i have understand how to include each other using foward referance*/
void create_class(int num);
Test_Class t_class;
~Test_Stage();
private:
};
#endif
Test_Stage
cpp:
#include"test_stage.h"
#include "test_class.h"// and as you see i included both files
Test_Stage::Test_Stage()
{
}
Test_Stage::Test_Stage(int num)
{
x = num;// a variable specific in this object(to test pointer)
create_class(num);
}
void Test_Stage::create_bullet(int damage, string name)
{
cout << "created damage: " << damage << " to " << x << endl;/*using the value
created in this object to see if pointer is actually working*/
}
void Test_Stage::create_class(int num)
{
Test_Class t_class = Test_Class(this, num);
}
Test_Stage::~Test_Stage()
{
}
Test_Class
.h:
#ifndef TEST_CLASS_H
#define TEST_CLASS_H
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include ".\luabind\luabind.hpp"
#include <iostream>
using namespace std;
class Test_Stage;
class Test_Class
{
public:
int x;
Test_Class();
Test_Class(Test_Stage* stage, int num);
void static shoot_a_bullet(intptr_t stg, int damage);
~Test_Class();
private:
};
#endif TEST_CLASS_H
And finally,Test_Class
.cpp:
#include "test_class.h"
#include"test_stage.h"
void Test_Class::shoot_a_bullet(intptr_t stg, int damage)
{
Test_Stage* stage = (Test_Stage*)stg; // intptr_t back to pointer
stage->create_bullet(damage, "wowo"); // use pointer
}
Test_Class::Test_Class()
{
}
Test_Class::Test_Class(Test_Stage* stg, int num)
{
intptr_t stage = (intptr_t)stg;
// Create a new lua state
lua_State *myLuaState = luaL_newstate();
// Connect LuaBind to this lua state
luabind::open(myLuaState);
luaL_openlibs(myLuaState);
luabind::module(myLuaState)[
luabind::def("shoot_a_bullet", &shoot_a_bullet)//again this is static now
];
luabind::globals(myLuaState)["stage"] = stage;
cout << "I'm here " << endl;//just to check how far did the program go
luaL_dostring(
myLuaState,
"shoot_a_bullet(stage, 134)\n"
);
cout << "I passed it"<< endl;
cin.get();
}
Test_Class::~Test_Class()
{
}
Have fun!
回答2:
I know this is late but why didnt you simple do
luabind::module(myLuaState)[
luabind::class_<Test_Class>("Test_Class")
.def("shoot_a_bullet", &Test_Class::shoot_a_bullet)
];
luabind::globals(myLuaState)["stage"] = stage;
luaL_dostring(
myLuaState,
"stage::shoot_a_bullet(134)\n"
);
You did everything right, if you want to call a member function of an exposed C++ object you first need to bind it (which you did) then you put your object into some lua scope (you used the global) and then you simple reference the object stage and call a function with ::myfunction
来源:https://stackoverflow.com/questions/21213495/rather-then-create-a-object-in-lua-how-let-lua-directly-tall-the-c-object-to