设为首页 加入收藏

TOP

LuaBridge为Lua绑定C/C++对象(一)
2014-04-06 17:35:29 来源: 作者: 【 】 浏览:222
Tags:LuaBridge Lua 绑定 C/C 对象

  最近为了总结Lua绑定C/C++对象的各种方法、第三方库和原理,学习了LuaBridge库为Lua绑定C/C++对象,下面是学习笔记,实质是对该库的Reference Manual基本上翻译了一遍,学习过程中测试代码,放在我的github上。

  LuaBridge的主要特点

  源码只有头文件,没有。cpp文件,没有MakeFile,使用时只需一个#include即可。

  支持不同的对象生命周期管理模式。

  对Lua栈访问方便并且是类型安全的(type-safe)。

  Automatic function parameter type binding.

  Easy access to Lua objects like tables and functions.

  LuaBridge的API是基于C++模板元编程(template metaprogramming)的。在编译时这些模板自动生成各种Lua API调用,从而可以再Lua脚本中使用C++程序中的类和函数。为了能在C++中使用Lua的数据,比如number,string,table以及方便调用Lua的函数,使用LuaBridge中的LuaRef类,可以方便做到。

  LuaBridge设计原则

  由于LuaBridge的设计目标尽可能方便使用,比如只有头文件、没有用到高级C++的语法、不需要配置。因此LuaBridge性能虽足够好,但并不是最好的,比如OOLua执行效率就比它好,并且它也不像LuaBind那样功能全面。LuaBridge不支持下面特性:

  枚举型常量

  不支持8个以上的函数或方法的调用

  重载函数、方法和构造函数(Overloaded functions, methods, or constructors)

  全局变量(变量必须被包装在命名空间里)

  自动地转换STL容器类型和Table

  在Lua中继承C++类(Inheriting Lua classes from C++ classes)。

  Passing nil to a C++ function that expects a pointer or reference

  Standard containers like std::shared_ptr

  在Lua访问C++

  为了在Lua中使用C++中的数据和函数,LuaBridge要求任何需要使用的数据的都需要注册。LuaBridge可以注册下面五种类型数据:

  Namespaces  一个Lua table包含了其他注册信息

  Data  全局变量或静态变量、数据成员或静态数据成员

  Functions  一般函数、成员函数或静态成员函数

  CFunctions  A regular function, member function, or static member function that uses the lua_CFunction calling convention

  Properties  Global properties, property members, and static property members. These appear like data to Lua,but are implemented in C++ using functions to get and set the values.

  Data和Properties在注册时被标记为只读(read-only)。这不同于const,这些对象的值能在C++中修改,但不能在Lua脚本中修改。

  Namespaces

  LuaBridge索引的注册都是在一个namespace中,namespace是从lua角度来看的,它实质上就是table,注意这里的namespace不是C++中的namespace,C++的namespace不是一定需要的。LuaBridge的namespace是对Lua脚本来说的,它们被作为逻辑组合工具(logical grouping tool)。为了访问Lua的全局命名空间(global namespace),可以在C++中,这样调用:

  <span style="font-size:14px;">getGlobalNamespace (L);</span>

  上面的调用会返回一个对象(实质是table)可用来进一步注册,比如:

  <span style="font-size:14px;">     getGlobalNamespace (L)

  .beginNamespace ("test");</span>

  上面的调用就会在Lua的_G中创建一个名为"test"的table,现在这个table还是空的。LuaBridge保留所有以双下划线开头命名的标识,因此__test是无效的命名,尽管这样命名LuaBridge不会报错。我们可以进一步扩展上面的注册:

  <span style="font-size:14px;">    getGlobalNamespace (L)

  .beginNamespace ("test")

  .beginNamespace ("detail")

  .endNamespace ()

  .beginNamespace ("utility")

  .endNamespace ()

  .endNamespace ();</span>

  这样注册后,我们就可以在Lua中使用test, test.detail,和test.utility.这里的引入的endNamespace函数,也会返回一个对象(实质也是table),该对象实质就是上一层namespace,表示当前namespace注册完成。 All LuaBridge functions which create registrations return an object upon which subsequent registrations can be made,allowing for an unlimited number of registrations to be chained together using the dot operator.在一个namespace中,注册相同命名的对象,对于LuaBridge来说是没有定义的行为。一个namespace可以多次使用增加更多的成员。比如下面两段代码是等价的:

  <span style="font-size:14px;">    getGlobalNamespace (L)

  .beginNamespace ("test")

  .addFunction ("foo", foo)

  .endNamespace ();

  getGlobalNamespace (L)

  .beginNamespace ("test")

  .addFunction ("bar", bar)

  .endNamespace ();</span>

  和

  <span style="font-size:14px;">    getGlobalNamespace (L)

  .beginNamespace ("test")

  .addFunction ("foo", foo)

  .addFunction ("bar", bar)

  .endNamespace ();</span>

  Data, Properties, Functions, and CFunctions

  Data, Properties, Functions, and CFunctions可以依次使用addVariable,, addProperty, addFunction, and addCFunction来注册。在Lua脚本中调用注册的函数时,LuaBridge会自动地传入相应的参数,并对参数类型转和检查。同样,函数的返回值也会自动处理。当前LuaBridge最多可处理8个参数。Pointers, references, and objectsof class type as parameters are treated specially.如果我们在C++中有以下定义:

  <span style="font-size:14px;">    int globalVar;

  static float staticVar;

  std::string stringProperty;

  std::string getString () { return stringProperty; }

  void setString (std::string s) { stringProperty = s; }

  int foo () { return 42; }

  void bar (char const*) { }

  int cFunc (lua_State* L) { return 0; }</span>

  为了在Lua使用这些变量和函数,我们可以按以下方式注册它们:

  <span style="font-size:14px;">    getGlobalNamespace (L)

  .beginNamespace ("test")

  .addVariable ("var1", &globalVar)

  .addVariable ("var2", &staticVar, false)     // read-only

  .addProperty ("prop1", getString, setString)

  .addProperty ("prop2", getString)            // read only

  .addFunction ("foo", foo)

  .addFunction ("bar", bar)

  .addCFunction ("cfunc", cFunc)

  .endNamespace ();

  </span>

  Variables在注册时,可以通过传递第二个参数为false,确保Variables不会在Lua被修改,默认第二个参数是true.Properties在注册时,若不传递set函数,则在脚本中是read-only.

  通过上面注册后,则下面表达式在Lua是有效的:

  <span style="font-size:14px;">    test        -- a namespace,实质就是一个table,下面都是table中的成员

  test.var1   -- a lua_Number variable

  test.var2   -- a read-only lua_Number variable

  test.prop1  -- a lua_String property

  test.prop2  -- a read-only lua_String property

  test.foo    -- a function returning a lua_Number

  test.bar    -- a function taking a lua_String as a parameter

  test.cfunc  -- a function with a variable argument list and multi-return</span>

  注意test.prop1和test.prop2引用的C++中同一个变量,然后test.prop2是read-only,因此在脚本中对test.prop2赋值,会导致运行时错误(run-time error)。在Lua按以下方式使用:

  <span style="font-size:14px;">    test.var1 = 5         -- okay

  test.var2 = 6         -- error: var2 is not writable

  test.prop1 = "Hello"  -- okay

  test.prop1 = 68       -- okay, Lua converts the number to a string.

  test.prop2 = "bar"    -- error: prop2 is not writable

  test.foo ()           -- calls foo and discards the return value

  test.var1 = foo ()    -- calls foo and stores the result in var1

  test.bar ("Employee") -- calls bar with a string

  test.bar (test)       -- error: bar expects a string not a table</span>

  Class Objects

     

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C/C++位操作初步 下一篇C++ 中的处理类型

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·C语言指针从入门到基 (2025-12-26 05:21:36)
·【C语言指针初阶】C (2025-12-26 05:21:33)
·C语言指针的定义和使 (2025-12-26 05:21:31)
·在 Redis 中如何查看 (2025-12-26 03:19:03)
·Redis在实际应用中, (2025-12-26 03:19:01)