LuaState
LuaState copied to clipboard
Create instances of C++ classes in Lua 5.1.x
I've noticed that the library is able to register C++ classes but you are unable to instantiate them in Lua. I've seen this kind of ability in another project similar to this one called Selene.
Let's say I have the following (test) class:
struct Vec3
{
// Member variables if possible.
float x, y, z;
// Code...
// Multiple constructors if possible.
Vec3() : x(0), y(0), z(0)
{ }
Vec3(float x, float y, float z) : x(x), y(y), z(z)
{ }
Vec3(const Vec3& vec) : x(vec.x), y(vec.y), z(vec.z)
{ }
// Code...
// Operators if possible.
Vec3 operator+(const Vec3& vec)
{ return Vec3(x + vec.x, y + vec.y, z + vec.z); }
Vec3 operator-(const Vec3& vec)
{ return Vec3(x - vec.x, y - vec.y, z - vec.z); }
// Code...
// Member functions if possible.
void zero()
{ x = y = z = 0; }
void negate()
{ x = -x; y = -y; z = -z; }
// Code...
// Getters and setters if necessary.
void set(float x, float y, float z)
{ this->x = x; this->y = y; this->z = z; }
void setx(float x) { this->x = x; }
void sety(float y) { this->y = y; }
void setz(float z) { this->z = z; }
float getx() { return x; }
float gety() { return y; }
float getz() { return z; }
// Code...
};
And after I register in in Lua I should be able to do:
-- Multiple constructors if possible.
empty = Vec3.new()
specific = Vec3.new(5, 9, 2)
copy = Vec3.new(empty)
-- Operators if possible but NOT! a complete requirement.
copy = copy + specific
-- Member functions if possible.
specific.negate()
copy.empty()
-- Getters and setters if necessary.
copy.set(82, 33, 76)
ex empty.getx();
ey empty.gety();
ez empty.getz();
-- And so on....
But only if it's possible and in Lua 5.1.5 because I need to use it with LuaJit. The current library worked with my small tests however I need to be able to create new objects in Lua.
Selene is for Lua 5.2+ and therefore incompatible with LuaJit which is why is it doesn't fit my needs.
I need some example to show how to bind to class, Can you show me?
Unfortunately you can't bind whole classes, but is quite easy to buy existing instances like iSLC wrote...
With std::bind
:
class Foo
{
int value;
public:
void add(int number) { value += number; }
void rem(int number) { value -= number; }
void mul(int number) { value *= number; }
void div(int number) { value /= number; }
Foo(lua::State& state, const char* name) : value(0) {
state.set(name ,lua::Table());
lua::Value instance = state[name];
instance.set("add", std::function<void(int)>(std::bind(&Foo::add, this, std::placeholders::_1)));
instance.set("rem", std::function<void(int)>(std::bind(&Foo::add, this, std::placeholders::_1)));
instance.set("mul", std::function<void(int)>(std::bind(&Foo::add, this, std::placeholders::_1)));
instance.set("div", std::function<void(int)>(std::bind(&Foo::add, this, std::placeholders::_1)));
}
};
Or with lambdas:
class Foo
{
public:
int value;
void add(int number) { value += number; }
void rem(int number) { value -= number; }
void mul(int number) { value *= number; }
void div(int number) { value /= number; }
Foo(lua::State& state, const char* name) : value(0) {
state.set(name ,lua::Table());
lua::Value instance = state[name];
instance.set("add", [this](int number) { add(number); });
instance.set("rem", [this](int number) { rem(number); });
instance.set("mul", [this](int number) { mul(number); });
instance.set("div", [this](int number) { div(number); });
}
};
Simple use case:
#include <LuaState.h>
int main()
{
lua::State state;
Foo foo(state, "my_instance");
state.doString("my_instance.add(10)");
state.doString("my_instance.mul(2)");
state.doString("my_instance.div(5)");
assert(foo.value == 4);
}
Got it, I need to write some wrap class for real class,wrap class works like lua module, This separate the lua world and c++ world, clearly. Some pattern maybe help us easy to know and use it.
Thnaks.