luna工具库

概述

luna库提供了几个lua开发的常见辅助功能:

  • lua/c++绑定
  • lua序列化与反序列化
  • 变长整数编码,用于lua序列化,当然也可以方便的用于其他场合

这里把代码编译成了动态库,由于代码非常简单,实际使用时也可以简单的复制文件到自己的工程.
lua_archiver引用了lz4库用于数据压缩(lz4.h+lz4.c).

lua/c++绑定库(luna.h, luna.cpp)支持Windows, Linux, macOS三平台,默认的luna.h实现需C++14支持.
如果编译器不支持C++14,也可以将其替换为C++11版本的luna11.h.
之所以实现这个lua/c++绑定,是出于以下的想法:

  • 希望所有事情在c++代码中就搞定,不希望额外再运行一个什么转换处理工具
  • 希望能够方便的导出一般C++函数,而不必写一大堆lua api调用代码
  • 希望能简单的处理导出对象的生命期
  • 希望能方便的在lua代码中对导出对象进行扩展,重载等
  • 希望使用尽可能简单,无需对luna库本身做任何初始化
  • 希望执行时无副作用,即没有全局或静态的数据,进程中存在多个lua_State时不会相互干扰

编译说明

luna同时支持Windows, Linux, MacOS三平台,编译器最低必须支持C++11,最好支持C++14,需要安装cmake.
在编译之前,应先编译安装lua,然后:

cd luna
mkdir build
cd build
cmake ..
make

在macos上,可能会遇到编译器默认没有搜索/usr/local/include 目录而导致找不到lua.hpp的问题.
解决办法是执行xcode-select --install,该命令不仅仅是安装命令行工具,还会设置相应的参数.

除了编译为动态库,也可以简单的将源码复制到工程中使用,如果打算这样用,那么注意:
luna.h并不直接存在,而是cmake根据编译环境选取的luna14.h或者luna11.h,你可以根据自己的环境选择即可.

C++导出全局函数

当函数的参数以及返回值是***基本类型***或者是***已导出类***时,可以直接用lua_register_function导出:

int func_a(const char* a, int b);
int func_b(my_export_class_t* a, int b);
some_export_class* func_c(float x); lua_register_function(L, func_a);
lua_register_function(L, func_b);
lua_register_function(L, func_c);

当然,你也可以导出lua标准的C函数.

导出类

首先需要在你得类声明中插入导出声明:

class my_class final
{
// ... other code ...
int func_a(const char* a, int b);
int func_b(some_class_t* a, int b);
char m_name[32];
public:
// 插入导出声明:
DECLARE_LUA_CLASS(my_class);
};

在cpp中增加导出表的实现:

EXPORT_CLASS_BEGIN(my_class)
EXPORT_LUA_FUNCTION(func_a)
EXPORT_LUA_FUNCTION(func_b)
EXPORT_LUA_STRING(m_name)
EXPORT_CLASS_END()

可以用带_AS的导出宏指定导出的名字,用带_R的宏指定导出为只读变量. 比如: EXPORT_LUA_STRING_AS(m_name, Name)

关于导出类(对象)的注意点

目前通过静态断言作了限制: 只能导出声明为final的类

这是为了避免无意间在父类和子类做出错误的指针转换 如果需要父类子类同时导出且保证不会出现这种错误,可以自行去掉这个断言

关于C++导出对象的生存期问题

注意,C++对象一旦被push进入lua,其生命期就交给lua的gc管理了,C++层面不能随便删除. 这些lua托管的对象在gc时,会默认调用delete,如果不希望调用delete,可以在对象中实现自定义gc方法: void __gc().   另外,由于lua的gc回收资源总是具有一定延迟的,所以如果C++对象持有较多的资源的话,最好显示释放资源或者在lua层面显示的调用gc.
对于已经push到lua的对象,如果想从C++解除引用,可以调用lua_detach(L, object);

class my_class final
{
// ...
public:
DECLARE_LUA_CLASS(my_class);
void __gc()
{
// lua gc时,如果存在本函数,那么会调用本函数取代默认的delete
}
};

lua中访问导出对象

lua代码中直接访问导出对象的成员/方法即可.

local obj = get_obj_from_cpp();
obj.func("abc", 123);
obj.name = "new name";

另外,C++对象导出到lua中是通过一个table来实现的,可以称之为影子对象. 不但可以在lua中访问C++对象成员,还可以有下面这些常见用法:

  • 重载(覆盖)对象上的C++导出方法.
  • 在影子对象上增加额外的成员变量和方法.
  • 在C++中调用lua中为对象增加的方法,参见lua_call_object_function.

C++中调用lua函数

目前提供了两种支持:

  • C++调用全局函数
  • C++调用全局table中的函数
  • C++调用导出对象上附加的函数.

下面以调用全局table中的函数为例:

function s2s.some_func(a, b)
return a + b, a - b, "tom";
end

上面的lua函数返回三个值,那么,可以在C++中这样调用:

lua_guard g(L); //用它来做栈保护
int x, y;
const char* name = nullptr;
// 小心,如果用char*做字符串返回值的话,确保name变量不要在lua_guard g的作用域之外使用
lua_call_table_function(L, nullptr, "s2s", "some_func", std::tie(x, y, name), 11, 2);

注意上面的lua_guard,它实际上做的事情是:

  1. 在构造时调用lua_gettop保存栈.
  2. 析构时调用lua_settop恢复栈.
// 注意这里由于需要传入abc三个参数,所以需要写一个std::tie()表示没有返回参数
lua_call_table_function(L, nullptr, "s2s", "some_func", std::tie(), a, b, c);

如果没有参数,也没有返回值,那就是最简单的写法了:

lua_call_table_function(L, nullptr, "s2s", "some_func");

lua luna工具库的更多相关文章

  1. lua工具库penlight--02表和数组

    类Python的List lua的优美之处在于把数组和关联数组都用table实现了(Python中叫list和dict,C++中叫vector和map). 一般我们把数字索引的table叫做list. ...

  2. 详解LUA开发工具及其环境配置

    LUA开发工具及其环境配置是本文要介绍的内容,主要是来了解并学习lua开发工具的使用和环境的配置,第一次接触LUA的话,就跟本人一起学习吧.看我能不能忽悠到你. LUA是语言,那么一定有编写的工具.第 ...

  3. wxWidgets与其他工具库的比较(上)

    本文是在wxWidgets Wiki上面找到的一篇,对比了wxWidgets和其他一些界面工具的特点.看到很多朋友在网上询问这些库各自的特点,我想先把这篇文章翻译出来——毕竟这也算是一篇官方的文章,应 ...

  4. 使用Lua的扩展库LuaSocket用例

    目录结构 LuaSocket 是 Lua 的网络模块库,它可以很方便地提供 TCP.UDP.DNS.FTP.HTTP.SMTP.MIME 等多种网络协议的访问操作. 它由两部分组成:一部分是用 C 写 ...

  5. 细说Java主流日志工具库

    概述 在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息. 在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子. 我们先来逐一了解一下主流日志工具. java.util ...

  6. JHChart 1.1.0 iOS图表工具库中文ReadMe

    JHChart(最新版本1.1.0) 好吧,的确当前的github上已经存有不少的iOS图表工具库,然而,当公司的项目需要图表时,几乎没有哪个第三方能够完全满足我的项目需求.无奈之下,本人不得不花费一 ...

  7. JHChart iOS图表工具库1.0.3新版本详解

    前言. 从2016年4月14日开始,本人着手开发了JHChart图表工具库.经过断断续续的开发,截止到现在,已经实现了折线图.柱状图.饼状图.环形图和表格样式的图表功能.为了方便使用,我已经将一个简单 ...

  8. 生成lua的静态库.动态库.lua.exe和luac.exe

    前些日子准备学习下关于lua coroutine更为强大的功能,然而发现根据lua 5.1.4版本来运行一段代码的话也会导致 "lua: attempt to yield across me ...

  9. [转]Android开源项目第二篇——工具库篇

    本文为那些不错的Android开源项目第二篇--开发工具库篇,主要介绍常用的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多 ...

随机推荐

  1. Mysql 中的伪列用法1

    SELECT ( @rowNO := @rowNo + 1 ) AS rowno, A.*FROM ( SELECT * FROM t_user ) a, ( SELECT @rowNO := 0 ) ...

  2. 自定义tag标签的方法

    JSP1.0中可以通过继承TagSupport或者BodyTagSupport来实现自定义的tag处理方法. JSP2.0中也支持另外一种更为简单的自定tag的方法,那就是直接讲JSP代码保存成*.t ...

  3. 201671010140. 2016-2017-2 《Java程序设计》java学习第十六周

    java学习第十六周-并发        本周,学习了Java中线程,并发的知识,在老师的带领下,进行了对知识的理解学习,以及对实验的运行讲解,对这一块内容掌握的还可以,在自主编程中,也能够完成.线, ...

  4. C#隐式类型局部变量&隐式类型数组

    [隐式类型局部变量] 可以赋予局部变量推断“类型”var 而不是显式类型.var 关键字指示编译器根据初始化语句右侧的表达式推断变量的类型.推断类型可以是内置类型.匿名类型.用户定义类型或 .NET ...

  5. Python 2.7 爬取51job 全国java岗位

      一页有50条数据一共2000页 分页是get分页 #!/usr/bin/python # encoding: utf-8 import requests import threading from ...

  6. Jquery+Ajax实现Select动态添加数据

    https://blog.csdn.net/zhengxiangwen/article/details/46480687 最近在工作中,遇到了一个关于select的问题.一般情况下,select下拉框 ...

  7. Python学习笔记_获取当前目录和上级目录

    实验目标:获取当前目录和上级目录 系统环境: 1.OS:Win10 64位 2.Pythoh 3.7 3.实验路径:C:\Work\Python\MergeExcel 代码参考: # -*- codi ...

  8. mybatis中使用懒加载实现一对多复杂查询

    1.包结构 2.pom配置 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&qu ...

  9. Python设计模式之"外观模式"实例讲解

    Python中设计模式之外观模式主张以分多模块进行代码管理而减少耦合,下面用实例来进行说明. 应用特性: 在很多复杂而小功能需要调用需求时,而且这些调用往往还有一定相关性,即一调用就是一系列的. 结构 ...

  10. VC6.0 中 添加/取消 块注释的Macro代码

    SAMPLE.DSM是微软提供的样例,使用的是vb语言.其中的 CommentOut 函数,是支持块注释的,可是这种/**/的注释方式,有时候用起来不是很方便,因为两个/会因为一个/而终止.对于大块代 ...