docs.rst.svn-base
来自「本人找过多个在linux下c++的lua5.1封装库,但很少.luabind已经」· SVN-BASE 代码 · 共 2,173 行 · 第 1/5 页
SVN-BASE
2,173 行
an OO-system in Lua. :: class 'lua_testclass' function lua_testclass:__init(name) self.name = name end function lua_testclass:print() print(self.name) end a = lua_testclass('example') a:print()Inheritance can be used between lua-classes:: class 'derived' (lua_testclass) function derived:__init() super('derived name') end function derived:print() print('Derived:print() -> ') lua_testclass.print(self) endHere the ``super`` keyword is used in the constructor to initialize the baseclass. The user is required to call ``super`` first in the constructor.As you can see in this example, you can call the base class member functions.You can find all member functions in the base class, but you will have to givethe this-pointer (``self``) as first argument.Deriving in lua---------------It is also possible to derive Lua classes from C++ classes, and overridevirtual functions with Lua functions. To do this we have to create a wrapperclass for our C++ base class. This is the class that will hold the Lua objectwhen we instantiate a Lua class.:: class base { public: base(const char* s) { std::cout << s << "\n"; } virtual void f(int a) { std::cout << "f(" << a << ")\n"; } }; struct base_wrapper : base, luabind::wrap_base { base_wrapper(const char* s) : base(s) {} virtual void f(int a) { call<void>("f", a); } static void default_f(base* ptr, int a) { return ptr->base::f(a); } }; ... module(L) [ class_<base, base_wrapper>("base") .def(constructor<const char*>()) .def("f", &base::f, &base_wrapper::default_f) ];.. Important:: Since MSVC6.5 doesn't support explicit template parameters to member functions, instead of using the member function ``call()`` you call a free function ``call_member()`` and pass the this-pointer as first parameter.Note that if you have both base classes and a base class wrapper, you must giveboth bases and the base class wrapper type as template parameter to ``class_`` (as done in the example above). The order in which you specifythem is not important. You must also register both the static version and thevirtual version of the function from the wrapper, this is necessary in orderto allow luabind to use both dynamic and static dispatch when calling the function... Important:: It is extremely important that the signatures of the static (default) function is identical to the virtual function. The fact that one of them is a free function and the other a member function doesn't matter, but the parameters as seen from lua must match. It would not have worked if the static function took a ``base_wrapper*`` as its first argument, since the virtual function takes a ``base*`` as its first argument (its this pointer). There's currently no check in luabind to make sure the signatures match.If we didn't have a class wrapper, it would not be possible to pass a Lua classback to C++. Since the entry points of the virtual functions would still pointto the C++ base class, and not to the functions defined in Lua. That's why weneed one function that calls the base class' real function (used if the luaclass doesn't redefine it) and one virtual function that dispatches the callinto luabind, to allow it to select if a Lua function should be called, or ifthe original function should be called. If you don't intend to derive from aC++ class, or if it doesn't have any virtual member functions, you can registerit without a class wrapper.You don't need to have a class wrapper in order to derive from a class, but ifit has virtual functions you may have silent errors. .. Unnecessary? The rule of thumb is: If your class has virtual functions, create a wrapper type, if it doesn't don't create a wrapper type.The wrappers must derive from ``luabind::wrap_base``, it contains a Lua referencethat will hold the Lua instance of the object to make it possible to dispatchvirtual function calls into Lua. This is done through an overloaded member function:: template<class Ret> Ret call(char const* name, ...)Its used in a similar way as ``call_function``, with the exception that it doesn'ttake a ``lua_State`` pointer, and the name is a member function in the Lua class... warning:: The current implementation of ``call_member`` is not able to distinguish const member functions from non-const. If you have a situation where you have an overloaded virtual function where the only difference in their signatures is their constness, the wrong overload will be called by ``call_member``. This is rarely the case though.Object identity~~~~~~~~~~~~~~~When a pointer or reference to a registered class with a wrapper is passedto Lua, luabind will query for it's dynamic type. If the dynamic typeinherits from ``wrap_base``, object identity is preserved.:: struct A { .. }; struct A_wrap : A, wrap_base { .. }; A* f(A* ptr) { return ptr; } module(L) [ class_<A, A_wrap>("A"), def("f", &f) ];:: > class 'B' (A) > x = B() > assert(x == f(x)) -- object identity is preserved when object is -- passed through C++This functionality relies on RTTI being enabled (that ``LUABIND_NO_RTTI`` isnot defined).Overloading operators---------------------You can overload most operators in Lua for your classes. You do this by simplydeclaring a member function with the same name as an operator (the name of themetamethods in Lua). The operators you can overload are: - ``__add`` - ``__sub`` - ``__mul`` - ``__div`` - ``__pow`` - ``__lt`` - ``__le`` - ``__eq`` - ``__call`` - ``__unm`` - ``__tostring````__tostring`` isn't really an operator, but it's the metamethod that is calledby the standard library's ``tostring()`` function. There's one strange behaviorregarding binary operators. You are not guaranteed that the self pointer youget actually refers to an instance of your class. This is because Lua doesn'tdistinguish the two cases where you get the other operand as left hand value orright hand value. Consider the following examples:: class 'my_class' function my_class:__init(v) self.val = v end function my_class:__sub(v) return my_class(self.val - v.val) end function my_class:__tostring() return self.val endThis will work well as long as you only subtracts instances of my_class witheach other. But If you want to be able to subtract ordinary numbers from yourclass too, you have to manually check the type of both operands, including theself object. :: function my_class:__sub(v) if (type(self) == 'number') then return my_class(self - v.val) elseif (type(v) == 'number') then return my_class(self.val - v) else -- assume both operands are instances of my_class return my_class(self.val - v.val) end endThe reason why ``__sub`` is used as an example is because subtraction is notcommutative (the order of the operands matters). That's why luabind cannotchange order of the operands to make the self reference always refer to theactual class instance.If you have two different Lua classes with an overloaded operator, the operatorof the right hand side type will be called. If the other operand is a C++ classwith the same operator overloaded, it will be prioritized over the Lua class'operator. If none of the C++ overloads matches, the Lua class operator will becalled.Finalizers----------If an object needs to perform actions when it's collected we provide a``__finalize`` function that can be overridden in lua-classes. The``__finalize`` functions will be called on all classes in the inheritancechain, starting with the most derived type. :: ... function lua_testclass:__finalize() -- called when the an object is collected endSlicing-------If your lua C++ classes don't have wrappers (see `Deriving in lua`_) andyou derive from them in lua, they may be sliced. Meaning, if an objectis passed into C++ as a pointer to its base class, the lua part will beseparated from the C++ base part. This means that if you call virtualfunctions on that C++ object, they will not be dispatched to the luaclass. It also means that if you adopt the object, the lua part will begarbage collected.:: +--------------------+ | C++ object | <- ownership of this part is transferred | | to c++ when adopted +--------------------+ | lua class instance | <- this part is garbage collected when | and lua members | instance is adopted, since it cannot +--------------------+ be held by c++. The problem can be illustrated by this example:: struct A {}; A* filter_a(A* a) { return a; } void adopt_a(A* a) { delete a; }:: using namespace luabind; module(L) [ class_<A>("A"), def("filter_a", &filter_a), def("adopt_a", &adopt_a, adopt(_1)) ]In lua:: a = A() b = filter_a(a) adopt_a(b)In this example, lua cannot know that ``b`` actually is the same object as``a``, and it will therefore consider the object to be owned by the C++ side.When the ``b`` pointer then is adopted, a runtime error will be raised becausean object not owned by lua is being adopted to C++.If you have a wrapper for your class, none of this will happen, see`Object identity`_.Exceptions==========If any of the functions you register throws an exception when called, thatexception will be caught by luabind and converted to an error string and``lua_error()`` will be invoked. If the exception is a ``std::exception`` or a``const char*`` the string that is pushed on the Lua stack, as error message,will be the string returned by ``std::exception::what()`` or the string itselfrespectively. If the exception is unknown, a generic string saying that thefunction threw an exception will be pushed.Exceptions thrown from user defined functions have to be caught by luabind. Ifthey weren't they would be thrown through Lua itself, which is usually compiledas C code and doesn't support the stack-unwinding that exceptions imply.Any function that invokes Lua code may throw ``luabind::error``. This exceptionmeans that a Lua run-time error occurred. The error message is found on top ofthe Lua stack. The reason why the exception doesn't contain the error stringitself is because it would then require heap allocation which may fail. If anexception class throws an exception while it is being thrown itself, theapplication will be terminated.Error's synopsis is:: class error : public std::exception { public: error(lua_State*); lua_State* state() const throw(); virtual const char* what() const throw(); };The state function returns a pointer to the Lua state in which the error wasthrown. This pointer may be invalid if you catch this exception after the luastate is destructed. If the Lua state is valid you can use it to retrieve theerror message from the top of the Lua stack.An example of where the Lua state pointer may point to an invalid statefollows:: struct lua_state { lua_state(lua_State* L): m_L(L) {} ~lua_state() { lua_close(m_L); } operator lua_State*() { return m_L; } lua_State* m_L; }; int main() { try { lua_state L = lua_open(); /* ... */ } catch(luabind::error& e) { lua_State* L = e.state(); // L will now point to the destructed // Lua state and be invalid /* ... */ } }There's another exception that luabind may throw: ``luabind::cast_failed``,this exception is thrown from ``call_function<>`` or ``call_member<>``. Itmeans that the return value from the Lua function couldn't be converted toa C++ value. It is also thrown from ``object_cast<>`` if the cast cannotbe made.The synopsis for ``luabind::cast_failed`` is:: class cast_failed : public std::exception { public: cast_failed(lua_State*); lua_State* state() const throw(); LUABIND_TYPE_INFO info() const throw(); virtual const char* what() const throw(); };Again, the state member function returns a pointer to the Lua state where theerror occurred. See the example above to see where this pointer may be invalid.The info member function returns the user defined ``LUABIND_TYPE_INFO``, whichdefaults to a ``const std::type_info*``. This type info describes the type thatwe tried to cast a Lua value to.If you have defined ``LUABIND_NO_EXCEPTIONS`` none of these exceptions will bethrown, instead you can set two callback functions that are called instead.These two functions are only defined if ``LUABIND_NO_EXCEPTIONS`` are defined.:: luabind::set_error_callback(void(*)(lua_State*))The function you set will be called when a runtime-error occur in Lua code. Youcan find an error message on top of the Lua stack. This function is notexpected to return, if it does luabind will call ``std::terminate()``.:: luabind::set_cast_failed_callback(void(*)(lua_State*, LUABIND_TYPE_INFO))The function you set is called instead of throwing ``cast_failed``. This functionis not expected to return, if it does luabind will call ``std::terminate()``.Policies========Sometimes it is necessary to control how luabind passes arguments and returnvalue, to do this we have policies. All policies use an index to associatethem with an argument in the function signature. These indices are ``result`` and ``_N`` (where ``N >= 1``). When dealing with member functions ``_1`` refersto the ``this`` pointer... contents:: Policies currently implemented :local: :depth: 1.. include:: adopt.rst.. include:: dependency.rst.. include:: out_value.rst
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?