[转] Quick Introduction to LuaBind
Lua is a great scripting language for games and regular applications
alike because it is fast, simple and well suited for embedding
(embedding means putting the scripting language into your application
instead of making your application an add-on module to the scripting
language). Lua can easily be compiled and setting up a lua
environment in your code is no big task either, because all you have to
do is call de>lua_open() de> and later de>lua_close() de>.
However, when the time comes to create bindings for your functions
and classes so scripts can call into your co
On
Getting your Hands on LuaBind Binaries
To use LuaBind, you have two options: Add all LuaBind sources to your project, or compile LuaBind into a static library which you can then link to your project. This article will follow the latter approach, because it is cleaner and you can more easily upgrade your projects to new versions of LuaBind.
To compile LuaBind, you would normally download the sources of Lua, Boost and LuaBind, set up and compile each library as well as possibly modify LuaBind due to changes in the Boost library which have not been reflected in LuaBind yet. Because this whole process can be somewhat troublesome, you can also download a single package containing precompiled binaries of Lua 5.1.4, LuaBind 0.8.1 and a minimal subset of Boost 1.39.0 for Microsoft Visual Studio 2008 or Microsoft Visual C++ 2008 Express here:
LuaBind 0.8.1 Binaries and Demo (use 7-Zip or WinRAR to extract)
You can then find a readily configured LuaBind example project which
compiles out-of-the-box as
Calling Lua Functions from C++
It doesn't get any easier than this. To call a function in a lua script from
C++, you can use LuaBind's
// Create a new lua state
lua_State *myLuaState = lua_open();
// Connect LuaBind to this lua state
luabind::open(myLuaState);
// Define a lua function that we can call
luaL_dostring(
myLuaState,
"function add(first, second)\n"
" return first + second\n"
"end\n"
);
cout << "Result: "
<< luabind::call_function<int>(myLuaState, "add", 2, 3)
<< endl;
lua_close(myLuaState);
}
Let's see, first we use
Making C++ functions callable from Lua
The next example is a bit more complicated. We want to call a C++
function from a lua script. Instead of wasting our time with lua stack
manipulation and da
cout << "hello world " << number << endl;
}
int main() {
// Create a new lua state
lua_State *myLuaState = lua_open();
// Connect LuaBind to this lua state
luabind::open(myLuaState);
// Add our function to the state's global scope
luabind::module(myLuaState) [
luabind::def("print_hello", print_hello)
];
// Now call our function in a lua script
luaL_dostring(
myLuaState,
"print_hello(123)\n"
);
lua_close(myLuaState);
}
As before, we need to connect LuaBind to the lua
state by using
If you need to export multiple functions, you should
seperate them from each other using commas (,).
You're not allowed to just end each definition with
a semicolon because they're still enclosed by the
Exporting Classes to Lua
Now on
public:
NumberPrinter(int number) :
m_number(number) {}
void print() {
cout << m_number << endl;
}
private:
int m_number;
};
int main() {
// Create a new lua state
lua_State *myLuaState = lua_open();
// Connect LuaBind to this lua state
luabind::open(myLuaState);
// Export our class with LuaBind
luabind::module(myLuaState) [
luabind::class_<NumberPrinter>("NumberPrinter")
.def(luabind::constructor<int>())
.def("print", &NumberPrinter::print)
];
// Now use this class in a lua script
luaL_dostring(
myLuaState,
"Print2000 = NumberPrinter(2000)\n"
"Print2000:print()\n"
);
lua_close(myLuaState);
}
This might look difficult, but on
The methods we're calling can be seen in the next
two lines where the class constructor is exported
(using a special auxiliary structure
Exporting class attributes and properties
LuaBind can also export a class' attributes
(variables defined in a class) or even simulate a
variable to lua by using the getter and setter
methods in a class. To make it a bit more
interesting, we're going to export two C++ template
structures now. The concept of templates does not
exist in lua, so we can on
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 *myLuaState = lua_open();
// Connect LuaBind to this lua state
luabind::open(myLuaState);
// Export our classes with LuaBind
luabind::module(myLuaState) [
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)
];
// Now use this class in a lua script
luaL_dostring(
myLuaState,
"MyBox = Box(Point(10, 20), Point(30, 40))\n"
"MyBox.UpperLeft.X = MyBox.LowerRight.Y\n"
);
lua_close(myLuaState);
}
As you can see, the lua script works perfectly with
both classes, despite the fact that on
You could now directly pass a
More!
If you ever made a typo while working your way
through this tutorial, you might have found yourself
in front of an ugly run-time error message. This is
due to the fact that luabind transforms lua errrors
into various exceptions, all derived from the common
We will now demonstrate this as well as explore some other useful parts of luabind:
ResourceManager() :
m_ResourceCount(0) {}
void loadResource(const string &sFilename) {
++m_ResourceCount;
}
size_t getResourceCount() const {
return m_ResourceCount;
}
size_t m_ResourceCount;
};
int main() {
// Create a new lua state
lua_State *myLuaState = lua_open();
// Connect LuaBind to this lua state
luabind::open(myLuaState);
// Export our class with LuaBind
luabind::module(myLuaState) [
luabind::class_<ResourceManager>("ResourceManager")
.def("loadResource", &ResourceManager::loadResource)
.property("ResourceCount", &ResourceManager::getResourceCount)
];
try {
ResourceManager MyResourceManager;
// Assign MyResourceManager to a global in lua
luabind::globals(myLuaState)["MyResourceManager"] = &MyResourceManager;
// Execute a script to load some resources
luaL_dostring(
myLuaState,
"MyResourceManager:loadResource(\"abc.res\")\n"
"MyResourceManager:loadResource(\"xyz.res\")\n"
"\n"
"ResourceCount = MyResourceManager.ResourceCount\n"
);
// Read a global from the lua script
size_t ResourceCount = luabind::object_cast<size_t>(
luabind::globals(myLuaState)["ResourceCount"]
);
cout << ResourceCount << endl;
}
catch(const std::exception &TheError) {
cerr << TheError.what() << endl;
}
lua_close(myLuaState);
}
The
This should be enough to get you up to speed with LuaBind. Experiment with the examples and then go read the LuaBind docs, they're not even harder to read than this article ;)
There's a lot more to LuaBind you can discover, like
operator overloading, deriving classes from each
other, read on
FYI
Someone has made the effort and translated this article into what I think is korean.
I can't understand a single word, but cheers dude, seriously cool :)
posted on 2009-11-11 10:32 Eric Xiang 阅读(887) 评论(0) 编辑 收藏 举报