docs.rst.svn-base
来自「本人找过多个在linux下c++的lua5.1封装库,但很少.luabind已经」· SVN-BASE 代码 · 共 2,173 行 · 第 1/5 页
SVN-BASE
2,173 行
`Boost.Ref`__.__ http://www.boost.org/doc/html/ref.htmlLike this:: int ret = call_function(L, "fun", boost::ref(val));If you want to use a custom error handler for the function call, see``set_pcall_callback`` under `pcall errorfunc`_.Using Lua threads-----------------To start a Lua thread, you have to call ``lua_resume()``, this means that youcannot use the previous function ``call_function()`` to start a thread. You haveto use:: template<class Ret> Ret resume_function(lua_State* L, const char* name, ...) template<class Ret> Ret resume_function(object const& obj, ...)and:: template<class Ret> Ret resume(lua_State* L, ...)The first time you start the thread, you have to give it a function to execute. i.e. youhave to use ``resume_function``, when the Lua function yields, it will return the firstvalue passed in to ``lua_yield()``. When you want to continue the execution, you just call``resume()`` on your ``lua_State``, since it's already executing a function, you don't passit one. The parameters to ``resume()`` will be returned by ``yield()`` on the Lua side.For yielding C++-functions (without the support of passing data back and forth between theLua side and the c++ side), you can use the yield_ policy.With the overload of ``resume_function`` that takes an object_, it is important that theobject was constructed with the thread as its ``lua_State*``. Like this:.. parsed-literal:: lua_State* thread = lua_newthread(L); object fun = get_global(**thread**)["my_thread_fun"]; resume_function(fun);Binding classes to Lua======================To register classes you use a class called ``class_``. Its name is supposed toresemble the C++ keyword, to make it look more intuitive. It has an overloadedmember function ``def()`` that is used to register member functions, operators,constructors, enums and properties on the class. It will return itsthis-pointer, to let you register more members directly.Let's start with a simple example. Consider the following C++ class:: class testclass { public: testclass(const std::string& s): m_string(s) {} void print_string() { std::cout << m_string << "\n"; } private: std::string m_string; };To register it with a Lua environment, write as follows (assuming you are usingnamespace luabind):: module(L) [ class_<testclass>("testclass") .def(constructor<const std::string&>()) .def("print_string", &testclass::print_string) ];This will register the class with the name testclass and constructor that takesa string as argument and one member function with the name ``print_string``.:: Lua 5.0 Copyright (C) 1994-2003 Tecgraf, PUC-Rio > a = testclass('a string') > a:print_string() a stringIt is also possible to register free functions as member functions. Therequirement on the function is that it takes a pointer, const pointer,reference or const reference to the class type as the first parameter. The restof the parameters are the ones that are visible in Lua, while the objectpointer is given as the first parameter. If we have the following C++ code:: struct A { int a; }; int plus(A* o, int v) { return o->a + v; }You can register ``plus()`` as if it was a member function of A like this:: class_<A>("A") .def("plus", &plus)``plus()`` can now be called as a member function on A with one parameter, int.If the object pointer parameter is const, the function will act as if it was aconst member function (it can be called on const objects).Overloaded member functions---------------------------When binding more than one overloads of a member function, or just bindingone overload of an overloaded member function, you have to disambiguatethe member function pointer you pass to ``def``. To do this, you can use anordinary C-style cast, to cast it to the right overload. To do this, you haveto know how to express member function types in C++, here's a short tutorial(for more info, refer to your favourite book on C++).The syntax for member function pointer follows:.. parsed-literal:: *return-value* (*class-name*::\*)(*arg1-type*, *arg2-type*, *...*)Here's an example illlustrating this:: struct A { void f(int); void f(int, int); };:: class_<A>() .def("f", (void(A::*)(int))&A::f)This selects the first overload of the function ``f`` to bind. The secondoverload is not bound.Properties----------To register a global data member with a class is easily done. Consider thefollowing class:: struct A { int a; };This class is registered like this:: module(L) [ class_<A>("A") .def_readwrite("a", &A::a) ];This gives read and write access to the member variable ``A::a``. It is alsopossible to register attributes with read-only access:: module(L) [ class_<A>("A") .def_readonly("a", &A::a) ];When binding members that are a non-primitive type, the auto generated getterfunction will return a reference to it. This is to allow chained .-operators.For example, when having a struct containing another struct. Like this:: struct A { int m; }; struct B { A a; };When binding ``B`` to lua, the following expression code should work:: b = B() b.a.m = 1 assert(b.a.m == 1)This requires the first lookup (on ``a``) to return a reference to ``A``, andnot a copy. In that case, luabind will automatically use the dependency policyto make the return value dependent on the object in which it is stored. So, ifthe returned reference lives longer than all references to the object (b inthis case) it will keep the object alive, to avoid being a dangling pointer.You can also register getter and setter functions and make them look as if theywere a public data member. Consider the following class:: class A { public: void set_a(int x) { a = x; } int get_a() const { return a; } private: int a; };It can be registered as if it had a public data member a like this:: class_<A>("A") .property("a", &A::get_a, &A::set_a)This way the ``get_a()`` and ``set_a()`` functions will be called instead ofjust writing to the data member. If you want to make it read only you can justomit the last parameter. Please note that the get function **has to beconst**, otherwise it won't compile. This seems to be a common source of errors.Enums-----If your class contains enumerated constants (enums), you can register them aswell to make them available in Lua. Note that they will not be type safe, allenums are integers in Lua, and all functions that takes an enum, will acceptany integer. You register them like this:: module(L) [ class_<A>("A") .enum_("constants") [ value("my_enum", 4), value("my_2nd_enum", 7), value("another_enum", 6) ] ];In Lua they are accessed like any data member, except that they are read-onlyand reached on the class itself rather than on an instance of the class.:: Lua 5.0 Copyright (C) 1994-2003 Tecgraf, PUC-Rio > print(A.my_enum) 4 > print(A.another_enum) 6Operators---------To bind operators you have to include ``<luabind/operator.hpp>``.The mechanism for registering operators on your class is pretty simple. You usea global name ``luabind::self`` to refer to the class itself and then you justwrite the operator expression inside the ``def()`` call. This class:: struct vec { vec operator+(int s); };Is registered like this:.. parsed-literal:: module(L) [ class_<vec>("vec") .def(**self + int()**) ];This will work regardless if your plus operator is defined inside your class oras a free function.If your operator is const (or, when defined as a free function, takes a constreference to the class itself) you have to use ``const_self`` instead of``self``. Like this:.. parsed-literal:: module(L) [ class_<vec>("vec") .def(**const_self** + int()) ];The operators supported are those available in Lua:.. parsed-literal:: + - \* / == < <=This means, no in-place operators. The equality operator (``==``) has a littlehitch; it will not be called if the references are equal. This means that the``==`` operator has to do pretty much what's it's expected to do.Lua does not support operators such as ``!=``, ``>`` or ``>=``. That's why youcan only register the operators listed above. When you invoke one of thementioned operators, lua will define it in terms of one of the avaliableoperators.In the above example the other operand type is instantiated by writing``int()``. If the operand type is a complex type that cannot easily beinstantiated you can wrap the type in a class called ``other<>``. For example:To register this class, we don't want to instantiate a string just to registerthe operator.:: struct vec { vec operator+(std::string); };Instead we use the ``other<>`` wrapper like this:.. parsed-literal:: module(L) [ class_<vec>("vec") .def(self + **other<std::string>()**) ];To register an application (function call-) operator:.. parsed-literal:: module(L) [ class_<vec>("vec") .def( **self(int())** ) ];There's one special operator. In Lua it's called ``__tostring``, it's notreally an operator. It is used for converting objects to strings in a standardway in Lua. If you register this functionality, you will be able to use the luastandard function ``tostring()`` for converting your object to a string.To implement this operator in C++ you should supply an ``operator<<`` forstd::ostream. Like this example:.. parsed-literal:: class number {}; std::ostream& operator<<(std::ostream&, number&); ... module(L) [ class_<number>("number") .def(**tostring(self)**) ];Nested scopes and static functions----------------------------------It is possible to add nested scopes to a class. This is useful when you need to wrap a nested class, or a static function... parsed-literal:: class_<foo>("foo") .def(constructor<>()) **.scope [ class_<inner>("nested"), def("f", &f) ]**;In this example, ``f`` will behave like a static member function of the class``foo``, and the class ``nested`` will behave like a nested class of ``foo``.It's also possible to add namespace's to classes using the same syntax.Derived classes--------------- If you want to register classes that derives from other classes, you canspecify a template parameter ``bases<>`` to the ``class_`` instantiation. Thefollowing hierarchy:: struct A {}; struct B : A {};Would be registered like this:: module(L) [ class_<A>("A"), class_<B, A>("B") ];If you have multiple inheritance you can specify more than one base. If B wouldalso derive from a class C, it would be registered like this:: module(L) [ class_<B, bases<A, C> >("B") ];Note that you can omit ``bases<>`` when using single inheritance... note:: If you don't specify that classes derive from each other, luabind will not be able to implicitly cast pointers between the types.Smart pointers--------------When you register a class you can tell luabind that all instances of that classshould be held by some kind of smart pointer (boost::shared_ptr for instance).You do this by giving the holder type as an extra template parameter tothe ``class_`` you are constructing, like this:: module(L) [ class_<A, boost::shared_ptr<A> >("A") ];You also have to supply two functions for your smart pointer. One that returnsthe type of const version of the smart pointer type (boost::shared_ptr<const A>in this case). And one function that extracts the raw pointer from the smartpointer. The first function is needed because luabind has to allow thenon-const -> conversion when passing values from Lua to C++. The secondfunction is needed when Lua calls member functions on held types, the this
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?