sbk*_*sbk 13
好问题.我对luabind如何做它有一些模糊的想法,但我不知道如何完全和准确地回答.有了IDE和调试器,我开始解析以下非常简单的部分:
struct C
{
int i;
int f(int x, const char* s)
};
lua_State* L = luaL_newstate();
open(L);
module(L)
[
class_<C>("C")
.def_readwrite("index", &C::i)
.def("f", &C::f)
];
Run Code Online (Sandbox Code Playgroud)
首先要注意的L
是传递给luabind很多,调用open
在Lua状态下创建一些全局变量:__luabind_classes
类型为userdata,两个函数class
和property
.Luabind似乎没有使用全局变量 - 它所需要的一切都保存在lua环境中.
现在我们来了module(L)[...]
.原始代码是最好的解释,首先在这里module
:
inline module_ module(lua_State* L, char const* name = 0)
{
return module_(L, name);
}
Run Code Online (Sandbox Code Playgroud)
很简单,这里是module_
:
class LUABIND_API module_
{
public:
module_(lua_State* L_, char const* name);
void operator[](scope s);
private:
lua_State* m_state;
char const* m_name;
};
Run Code Online (Sandbox Code Playgroud)
所以我们的小程序所做的就是在module_
类上调用operator []并使用一些定义(这是scope
参数),但是module_
类知道要运行哪个Lua状态.该scope
班也是有趣的看(部分被省略,有些略微简化的):
struct LUABIND_API scope
{
//...
explicit scope(detail::registration* reg);
scope& operator,(scope s);
void register_(lua_State* L) const;
private:
detail::registration* m_chain;
};
Run Code Online (Sandbox Code Playgroud)
scope
正在建立一个链接的detail::registration
节点列表,该列表来自使用operator,
.所以,当一个呢module(L) [class_<...>..., class_<...>...]
,class_
它继承自scope
初始化其与基础detail::registration
实例,然后的逗号操作符scope
建立所有注册的链接列表,这传递给module_::operator[]
它调用scope::register_
这反过来又列举了链,并呼吁register_
所有的detail::registration
对象.将lua_State
始终被传递到register_
.
唷.现在让我们看看当一个人发生了什么class_<C>("C").def("f", &C::f)
.这构造了一个class_<C>
具有某个名称的实例,该实例位于该detail::registration
成员中class_
.调用class_::def
方法会在reg结构和诸如此类的东西中写入,但这里的调用链中更深层次的一条非常有趣的行def
:
object fn = make_function(
L, f, deduce_signature(f, (Class*)0), policies);
Run Code Online (Sandbox Code Playgroud)
噢,deduce_signature
我真的很想看到.现在我想要看到它,但它的工作方式是:通过boost(BOOST_PP_ITERATE
和其他一些实用程序)辅助的暗预处理器巫术,为一个和LUABIND_MAX_ARITY之间的每个N生成以下内容:
template <class R, class T, class A1, classA2, ..., classAN>
boost::mpl::vectorN_PLUS_2<R, T, A1, A2, ..., AN> // type of return value
deduce_signature(R(T::*)(A1, A2, ..., AN))
{
return boost::mpl::vectorN_PLUS_2<R, T, A1, A2, ..., AN>()
}
Run Code Online (Sandbox Code Playgroud)
同样,为1和LUABIND_MAX_ARITY之间的所有N生成这样的函数,默认情况下为10.有几个重载来处理const方法,虚拟包装器和自由函数等,这意味着大约有50个deduce_signature
函数在预处理器之后和编译开始之前最终出现在源代码中.从那里开始,编译器的工作就是deduce_signature
为你传递给def
它的函数选择正确的重载,并返回正确的boost::mpl::vectorX
类型.从那里make_function
可以做任何事情 - 它有一个参数类型的[编译时]列表,通过一些模板魔术,这些被计算,转换为Lua值和从Lua值转换,依此类推.
这是我会停下来的地方.调查基于Luabind 0.8.1.随意浏览/调试Luabind的代码以获得更多答案 - 这需要一些时间,但是在你习惯了这种风格之后并没有那么难:)祝你好运.
TL; DR:魔术......黑魔法
归档时间: |
|
查看次数: |
1513 次 |
最近记录: |