UDLua

UDLua

https://zhuanlan.zhihu.com/p/356694688

Lua 只有“贫瘠”的 oop,利用元表实现,功能满满但十分原始。我来试着改善这个体验。

我前段时间写了一篇关于 C++ 动态反射库的文章

https://zhuanlan.zhihu.com/p/337200770

实际上,我这个动态库,设计已经出色到可以轻松成为一个跨语言的类型框架。

本文就来演示一下 Lua 装配上 C++ OOP 后可以多神奇!

项目地址:

https://github.com/Ubpa/UDLua

How to use

the example code is here

Suppose you need to use struct vec

struct vec {
  float x;
  float y;
  float norm() const { return std::sqrt(x * x + y * y); }
};

Manual registration on Lua

if you want to do it on C++, check out this link ->.

local vec = UDRefl.RegisterType({
  type = "vec",
  fields = {
    { type = "float32", name = "x" },
    { type = "float32", name = "y" },
  },
  methods = {
    {
      name = "norm",
      result = "float32",
      body = function (p)
        return math.sqrt(UDRefl.unbox(p.x * p.x + p.y * p.y))
      end
    }
  }
})

Iterate over members

for iter in ObjectView.new(vec):GetFields():__range() do
  local name, info = iter:__indirection():__tuple_bind()
  print(name:GetView())
end

for iter in ObjectView.new(vec):GetMethods():__range() do
  local name, info = iter:__indirection():__tuple_bind()
  print(name:GetView())
end

Constructing types

v = SharedObject.new(vec)
print(v:GetType():GetName()) -- prints "vec"

Set/get variables

v.x = 3
v.y = 4
print("x: " .. v.x) -- prints "3"

Invoke Methods

print("norm: " .. v:norm()) -- prints "5"

Iterate over varables

for iter in v:GetTypeFieldVars():__range() do
  local name, var = iter:__indirection():__tuple_bind()
  print(name:GetView() .. ": ".. var)
end

Compiler compatibility

  • Clang/LLVM >= 10.0
  • GCC >= 10.0
  • MSVC >= 1926

Tested platforms:

  • Windows 10: VS2019 16.8.5

  • Ubuntu 20: GCC 10.2, Clang 11.0

  • MacOS 11.0 : GCC 10.2

    AppleClang 12 and Clang 11 is not supported

0x02. 设计思路

步骤如下

  • 开发一套世界最强的 C++ 动态反射库 UDRefl
  • 将 UDRefl 中的接口完全注册到其自身中,实现自举
  • 在 lua 中注册 UDRefl,从而 lua 可以借助 UDRefl 操作其上已注册的类型

这里 UDRefl 扮演的角色是公共类型架构,以 C++ 的 OOP 作为主要参考对象,从而类型架构的性能与能力都充分好。

而 Lua 只是对接该公共类型架构的一个示例。日后还可以对接 C#,python 等。

0x03. 类型

一个类型由类名,基类列表,域,方法以及相应属性而组成。

类名支持类型系统,基于 C++,支持 const,&,&&。举例说,当你注册了 vec 类型,你可以使用 const{vec},从而禁止成员变量修改。

类名的细节请参考 C++ 生成式的编译期类型名

对象的空间设计成连续的,与 C/C++ 一致,根据基类和域的大小与对齐就可以自动算出基类偏移和域偏移。

方法分成员variable函数,成员const函数,静态函数。其中成员函数会将首个参数设置成 this。对于特殊的函数(构造,析构,运算符等),用户可将其命名成meta函数名(__ctor__dtor__add__mul等),当在 lua 使用 SharedObject.new,运算符时,会去调用这些函数。

0x04. 域

在 C++ 中使用 UDRefl 时,获取域的方式为 v.Var("x"),而在 Lua 中就十分自然,可直接写成 v.x

需要特别注意的是 Lua 中的对对象本身的赋值没法用元表重定义(但对对象成员的赋值是可以重定义的),所以我设计了特殊的域名 self用来获取它本身,示例为 v.self = w

0x05. 方法

在 C++ 中使用 UDRefl 时,方法调用的方式为 v.Invoke("norm"),而在 Lua 中就十分自然,可直接写成 v:norm()

类型定义中,使用类型数组 params 来声明参数类型。函数调用时,支持参数的自动类型转换,只要形参类型存在实参类型的构造函数即可,并且支持 &/&& 的各种转换(如 int-> int&&)。

另外还支持泛型参数,就像 C++ 的模板一样。即,当参数类型为 Ubpa::UDRefl::ObjectView 时,UDRefl 就将其视为泛型。

支持成员函数,这时第一个参数就是 this

0x06. 属性

属性 Attribute 同于 C# 的 Attribute,也就是挂在域,方法和类型上的对象。属性的类型完全可以是用户自定义的类型,并且支持任意的初始化。

============= End

原文地址:https://www.cnblogs.com/lsgxeva/p/14579972.html