luabind使用指南 - 进阶篇之converter和policy
本文内容来自对下面文章的整理:
- luabind的converter和policy
- Problem in luabind with default_converter and tables
- Luabind: Register custom converter
类型的converter
在C++和lua之间传递数据需要为各类型的数据进行相应的转换,luabind 内建了对基础类型数据和 std::string 的自动转换,都是通过 default_converter 来把 call_function 的调用参数压入lua调用栈,所有的 default_converter 特化都可以在 policy.hpp 中找到。
下面的代码实现 vector<string> 的类型转换:
1 namespace luabind {
2
3 // default_converter 的 vector<T> 特化
4 template <class T>
5 struct default_converter<vector<T> >
6 : native_converter_base<vector<T> >
7 {
8 // 检查栈中数据类型是否符合
9 static int compute_score(lua_State* L, int index) {
10 return (lua_type(L, index) == LUA_TTABLE ) ? 0 : -1;
11 }
12
13 // 从栈中取数据
14 vector<T> from(lua_State* L, int index) {
15 vector<T> container;
16 luabind::object tbl(from_stack(L, index));
17
18 for (luabind::iterator itr(tbl), end; itr != end; ++itr) {
19 boost::optional<T> v = object_cast_nothrow<T>(*itr);
20 if (v) {
21 container.push_back(*v);
22 }
23 }
24
25 return container;
26 }
27
28 // 将数据写入栈中
29 void to(lua_State* L, const vector<T>& container) {
30 lua_createtable(L, container.size(), 0);
31
32 luabind::object tbl(from_stack(L, -1));
33 int n = 0;
34 typename vector<T>::const_iterator itr;
35 for (itr = container.begin(); itr != container.end(); ++itr) {
36 tbl[++n] = *itr;
37 }
38 }
39
40 };
41
42 template <class T>
43 struct default_converter<const vector<T>&>
44 : default_converter<vector<T> >
45 {};
46 }
2
3 // default_converter 的 vector<T> 特化
4 template <class T>
5 struct default_converter<vector<T> >
6 : native_converter_base<vector<T> >
7 {
8 // 检查栈中数据类型是否符合
9 static int compute_score(lua_State* L, int index) {
10 return (lua_type(L, index) == LUA_TTABLE ) ? 0 : -1;
11 }
12
13 // 从栈中取数据
14 vector<T> from(lua_State* L, int index) {
15 vector<T> container;
16 luabind::object tbl(from_stack(L, index));
17
18 for (luabind::iterator itr(tbl), end; itr != end; ++itr) {
19 boost::optional<T> v = object_cast_nothrow<T>(*itr);
20 if (v) {
21 container.push_back(*v);
22 }
23 }
24
25 return container;
26 }
27
28 // 将数据写入栈中
29 void to(lua_State* L, const vector<T>& container) {
30 lua_createtable(L, container.size(), 0);
31
32 luabind::object tbl(from_stack(L, -1));
33 int n = 0;
34 typename vector<T>::const_iterator itr;
35 for (itr = container.begin(); itr != container.end(); ++itr) {
36 tbl[++n] = *itr;
37 }
38 }
39
40 };
41
42 template <class T>
43 struct default_converter<const vector<T>&>
44 : default_converter<vector<T> >
45 {};
46 }
下面是使用 vector<string> converter 的示例程序:
1 void test1(const vector<string>& v) {
2 copy(v.begin(), v.end(), ostream_iterator<string>(cout, "\n"));
3 }
4
5 vector<string> test2() {
6 vector<string> r;
7
8 r.push_back("r");
9 r.push_back("g");
10 r.push_back("b");
11
12 return r;
13 }
14
15 int main() {
16 lua_State* L = lua_open();
17 luaL_openlibs(L);
18
19 luabind::open(L);
20
21 luabind::module(L)
22 [
23 luabind::def("test1", &test1),
24 luabind::def("test2", &test2)
25 ];
26
27 luaL_dostring(L, "test1({\"1\",\"2\",\"3\"}) vec = test2() for k, v in ipairs(vec) do print(k..\":\"..v) end");
28 lua_close(L);
29
30 return 0;
31 }
2 copy(v.begin(), v.end(), ostream_iterator<string>(cout, "\n"));
3 }
4
5 vector<string> test2() {
6 vector<string> r;
7
8 r.push_back("r");
9 r.push_back("g");
10 r.push_back("b");
11
12 return r;
13 }
14
15 int main() {
16 lua_State* L = lua_open();
17 luaL_openlibs(L);
18
19 luabind::open(L);
20
21 luabind::module(L)
22 [
23 luabind::def("test1", &test1),
24 luabind::def("test2", &test2)
25 ];
26
27 luaL_dostring(L, "test1({\"1\",\"2\",\"3\"}) vec = test2() for k, v in ipairs(vec) do print(k..\":\"..v) end");
28 lua_close(L);
29
30 return 0;
31 }