Jump to content
  • Advertisement
Sign in to follow this  

Luabind and get_globals

This topic is 4603 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, Another Lua beginner here. I am using the tutorials at LunaticSystems. I passed an instance of a Box<float> into the luastate using get_globals. In the lua script that is executed, the box is modified. When I print the box property out in C++ after the script has executed, the property remains unchanged. I was under the impression that the changes made in Lua are reflected in C++. How does this work exactly? I have posted code below. As you can see, I have even tried getting the Box back out of the script in the hope that it has been changed, but it has not. Your help is appreciated.
// Include the lua headers (the extern "C" is a requirement because we're
// using C++ and lua has been compiled as C code)
extern "C" {
  #include "lua/lua.h"
  #include "lua/lauxlib.h"
}

// This is the only header we need to include for LuaBind to work
#include "luabind/luabind.hpp"

// Some other C++ headers we're most likely going to use
#include <iostream>
#include <string>

// We don't want to write std:: every time we're displaying some debug output
using namespace std;

template<typename T>
struct Point {
  Point(T X, T Y) :
    X(X), Y(Y) {}

  T X, Y;
};

template<typename T>
struct Box {
  Box(Point<T> UpperLeft, Point<T> LowerRight) :
    UpperLeft(UpperLeft), LowerRight(LowerRight) {}

  Point<T> UpperLeft, LowerRight;
};

int main() {
  // Create a new lua state
  lua_State *pMyLuaState = lua_open();

  // Connect LuaBind to this lua state
  luabind::open(pMyLuaState);

  // Export our classes with LuaBind
  luabind::module(pMyLuaState) [
    luabind::class_<Point<float> >("Point")
      .def(luabind::constructor<float, float>())
      .def_readwrite("X", &Point<float>::X)
      .def_readwrite("Y", &Point<float>::Y),

    luabind::class_<Box<float> >("Box")
      .def(luabind::constructor<Point<float>, Point<float> >())
      .def_readwrite("UpperLeft", &Box<float>::UpperLeft)
      .def_readwrite("LowerRight", &Box<float>::LowerRight)
  ];

  Box<float> box(Point<float>(10, 20), Point<float>(30, 40));
  cout << box.UpperLeft.X << endl;
  luabind::get_globals(pMyLuaState)["MyBox"] = &box;

  // Now use this class in a lua script
  lua_dostring(
    pMyLuaState,
    "MyBox.UpperLeft.X = MyBox.LowerRight.Y\n"
	"MyBox.UpperLeft.X = 1000"
  );

  box = luabind::object_cast<Box<float> >(
     luabind::get_globals(pMyLuaState)["MyBox"]
  );

  cout << box.UpperLeft.X << endl;

  lua_close(pMyLuaState);
}

Share this post


Link to post
Share on other sites
Advertisement
I have found that I am able to make those changes only if I get the object back out using the get_globals function as is done in the following line:


box = luabind::object_cast<Box<float> >(
luabind::get_globals(pMyLuaState)["MyBox"]
);


So the question boils down to this. If I pass an instance of a class into Lua and update the value in a script, will the changes be reflected in the host application?

Share this post


Link to post
Share on other sites
To add to the question above, why do I have to call the constructor on the Box within the script in order to modify it within the script? Just wondering.

The only changes made to the object within the script are made when the constructor is called. Any attempts to change the properties of the object are not successful.

The following code outputs 50 and then 1000 whereas I expected it to output 5000.


//Box<float> box = new Box<float>(Point<float>(50, 20), Point<float>(30, 40));
Box<float> box(Point<float>(50, 20), Point<float>(30, 40));

cout << box.UpperLeft.X << endl;

luabind::get_globals(pMyLuaState)["MyBox"] = (&box);

//"MyBox = Box(Point(10, 20), Point(30, 40))\n"
// Now use this class in a lua script
lua_dostring(
pMyLuaState,
"MyBox.UpperLeft.X = MyBox.LowerRight.Y\n"
"MyBox = Box(Point(10, 20), Point(30, 40))\n"
"MyBox.UpperLeft = Point(1000, 1000)\n"
"MyBox.UpperLeft.X = 5000\n"
);

box = luabind::object_cast<Box<float>& >(
luabind::get_globals(pMyLuaState)["MyBox"]);

cout << box.UpperLeft.X << endl;

Share this post


Link to post
Share on other sites
To answer my own question, the changes are reflected back in C++. So I pass an instance of an class into lua and modify it in the script. Afterwords, the changes are visible in C++ ONLY IF the property changed in the object is a simple value such as an int. If the object changed is an instance of a class, it does not allow me to change it unless I do so through a constructor.

So in the code above, I cannot change MyBox.UpperLeft.X directly. I can only modify it by setting MyBox.UpperLeft through its constructor like so:


// This does not make a change:
MyBox.UpperLeft.X = 20
// This does make a change:
MyBox.UpperLeft = Point(20, 20)


Is this just the way it is?

[Edited by - CodeNow on October 11, 2005 10:08:33 AM]

Share this post


Link to post
Share on other sites
It seems like it is getting more difficult to get on this site nowadays, but in this instance, I have grown from the experience since I was forced to find my own solution on this.

I am posting a complete piece of code that illustrates bind C++ objects to Lua. Hope this helps any of the other beginners.


// Include the lua headers (the extern "C" is a requirement because we're
// using C++ and lua has been compiled as C code)
extern "C" {
#include "lua/lua.h"
#include "lua/lauxlib.h"
}

// This is the only header we need to include for LuaBind to work
#include "luabind/luabind.hpp"

// Some other C++ headers we're most likely going to use
#include <iostream>
#include <string>

// We don't want to write std:: every time we're displaying some debug output
using namespace std;

// A templated 3D vertex
template<class T>
class Vertex
{
public:
Vertex(T ax, T ay, T az) : x(ax), y(ay), z(az) { }
T x;
T y;
T z;
};

// Non-templated 2D integer vertex
class Vert
{
public:
Vert(int ax, int ay) : x(ax), y(ay) { }
int x;
int y;
};

// A player who lives in 2D and 3D
class Player
{
public:
Player(int h, int m) : hp(h), mp(m), pos(Vertex<int>(0, 0, 0)), v(Vert(0, 0)) { }
void SetHealth(int h) { hp = h; }
void SetPos(int x, int y, int z) { pos.x = x; pos.y = y; pos.z = z; }
Vertex<int>& GetPos() { return pos; }
int hp;
int mp;
Vert v;
Vertex<int> pos;
};

int main() {
// Create a new lua state
lua_State *pMyLuaState = lua_open();

// Connect LuaBind to this lua state
luabind::open(pMyLuaState);

// Export our classes with LuaBind
// Note that Player does not share "pos" with Lua
// Instead, the GetPos returns pos by reference
luabind::module(pMyLuaState) [
luabind::class_<Vertex<int> >("Vertex")
.def(luabind::constructor<int, int, int>())
.def_readwrite("x", &Vertex<int>::x)
.def_readwrite("y", &Vertex<int>::y)
.def_readwrite("z", &Vertex<int>::z),

luabind::class_<Vert>("Vert")
.def(luabind::constructor<int, int>())
.def_readwrite("x", &Vert::x)
.def_readwrite("y", &Vert::y),

luabind::class_<Player>("Player")
.def(luabind::constructor<int, int>())
.def_readwrite("hp", &Player::hp)
.def_readwrite("mp", &Player::mp)
.def_readwrite("v", &Player::v)
.def("SetHealth", &Player::SetHealth)
.def("SetPos", &Player::SetPos)
.def("GetPos", &Player::GetPos)
];

// Objects to share with Lua
Vertex<int> v(20, 20, 20);
Player p(100, 100);

// Let Lua know
luabind::get_globals(pMyLuaState)["player1"] = (&p);
luabind::get_globals(pMyLuaState)["vert"] = (&v);

// A script using the objects
lua_dostring(
pMyLuaState,
"-- Set the player's magic points\n"
"player1.mp = 44\n"
"-- Set the player's health WAY TOO HIGH\n"
"player1:SetHealth(400)\n"
"-- Cheater!\n"
"player1.hp = 9999\n"
"-- Set the player's 3D position\n"
"player1:SetPos(55, 66, 77)\n"
"-- Attempt to change the 2D X position (Does not work)\n"
"player1.v.x = 66\n"
"-- Set the vertex X position\n"
"vert.x = 77\n"
"-- Set the 3D X position through the accessor (works)\n"
"player1:GetPos().x = 88\n"
);

// Output the results
cout << p.hp << endl;
cout << p.mp << endl;
cout << p.pos.x << endl;
cout << p.v.x << endl;
cout << v.x << endl;

lua_close(pMyLuaState);
}

Share this post


Link to post
Share on other sites
It looks like I'm not the only person who has found the lack of luabind related help on this forum a bit exasperating :)

I too am a luabind/lua newbie, Its a bit of a steep learning curve with the lua/luabind docs, they're not the greatest :)

I've found the best source of help to be the luabind-users mailing list, every query i've posted to them over the last few days has been answered nd answered well within hours, and in some cases minutes!

Share this post


Link to post
Share on other sites
The lack of help is probably down to the lack of experiance with it, while I've used it I dont claim to be a guru of any sort and I dare say the same applies to others around here, I guess things will improve in time as people use it more (ro dont, as the case might be)

and I should probably subscribe to that list myself [smile]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!