• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >Lua > Lua和C语言的交互详解

Lua和C语言的交互详解

作者: 字体:[增加 减小] 来源:互联网

通过本文主要向大家介绍了c语言调用lua,lua 详解,lua源码详解与应用,c lua,lua调用c函数等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

前言

对于Lua的基础总结总算告一段落了,从这篇博文开始,我们才真正的进入Lua的世界,一个无聊而又有趣的世界。来吧。

Lua语言是一种嵌入式语言,它本身的威力有限;当Lua遇见了C,那它就展示了它的强大威力。C和Lua是可以相互调用的。第一种情况是,C语言拥有控制权,Lua是一个库,这种形式中的C代码称为“应用程序代码”;第二种情况是,Lua拥有控制权,C语言是一个库,这个时候C代码就是“库代码”。“应用程序代码”和“库代码”都使用同样的API来与Lua通信,这些API就称为C API。

C API是一组能使C代码与Lua交互的函数,包括很多对Lua代码的操作。如何操作,操作什么,我们的文章我都会一一总结。C API是非常灵活而强大的。为了表示它的NB之处,不先来一段小的DEMO程序展示一下,怎么能够行呢?

#include <iostream>
#include <string.h>
 
extern "C"
{
    #include "lua.h"
    #include "lauxlib.h"
    #include "lualib.h"
}
int main()
{
    char buff[256] = {0};
    int error;
    lua_State *L = luaL_newstate(); // 打开Lua
    luaL_openlibs(L); // 打开标准库
    while (fgets(buff, sizeof(buff), stdin) != NULL)
    {
        error = luaL_loadbuffer(L, buff, strlen(buff), "line")
            || lua_pcall(L, 0, 0, 0);
        if (error)
        {
            fprintf(stderr, "%s", lua_tostring(L, -1));
            lua_pop(L, 1); // 从栈中弹出错误消息
        }
    }
 
    lua_close(L);
    return 0;
}
</div>

如果你没有接触过C API,对于上面这段代码,你肯定不会明白它是干什么的。什么也不说,你运行一下吧。然后输入Lua语句,看看运行结果。

先对上述代码引入的几个头文件进行解释一下:

头文件lua.h定义了Lua提供的基础函数,包括创建Lua环境、调用Lua函数、读写Lua环境中全局变量,以及注册供Lua调用的新函数等等;

头文件lauxlib.h定义了辅助库提供的辅助函数,它的所有定义都以LuaL_开头。辅助库是一个使用lua.h中API编写出的一个较高的抽象层。Lua的所有标准库编写都用到了辅助库;辅助库主要用来解决实际的问题。辅助库并没有直接访问Lua的内部,它都是用官方的基础API来完成所有工作的;

头文件lualib.h定义了打开标准库的函数。Lua库中没有定义任何全局变量。它将所有的状态都保存在动态结构lua_State中,所有的C API都要求传入一个指向该结构的指针。luaL_newstate函数用于创建一个新环境或状态。当luaL_newstate创建一个新的环境时,新的环境中并没有包含预定义的函数(eg.print)。为了使Lua保持灵活,小巧,所有的标准库都被组织到了不同的包中。当我们需要使用哪个标准库时,就可以调用lualib.h中定义的函数来打开对应的标准库;而辅助函数luaL_openlibs则可以打开所有的标准库。

头文件说完了,如果对代码中的extern “C”不懂的同学,请看这里。然后,就没有然后了,然后我就先不解释了,等我将后面的内容总结完,再回过头来看,你会明白的更彻底。点击这里去下载完整项目工程。

栈

Lua和C语言通信的主要方法是一个无处不在的虚拟栈。几乎所有的API调用都会操作这个栈上的值;所有的数据交换,无论是Lua到C语言或C语言到Lua都通过这个栈来完成。栈可以解决Lua和C语言之间存在的两大差异,第一种差异是Lua使用垃圾收集,而C语言要求显式地释放内存;第二种是Lua使用动态类型,而C语言使用静态类型。

为了屏蔽C和Lua之间的差异性,让彼此之间的交互变的通常,便出现了这个虚拟栈。栈中的每个元素都能保存任何类型的Lua值,当在C代码中要获取Lua中的一个值时,只需调用一个Lua API函数,Lua就会将指定值压入栈中;要将一个值传给Lua时,需要先将这个值压入栈,然后调用Lua API,Lua就会获得该值并将其从栈中弹出。为了将C类型的值压入栈,或者从栈中获取不同类型的值,就需要为每种类型定义一个特定的函数。是的,我们的确是这么干的。

Lua严格地按照LIFO规范来操作这个栈。但调用Lua时,Lua只会改变栈的顶部。不过,C代码则有更大的自由度,它可以检索栈中间的元素,甚至在栈的任意位置插入或删除元素。

压入栈

对于每种可以呈现在Lua中的C类型,API都有一个对应的压入函数,我这里把它们都列出来:
void lua_pushnil(lua_State *L);
void lua_pushboolean(lua_State *L, int bool);
void lua_pushnumber(lua_State *L, lua_Number n);
void lua_pushinteger(lua_State *L, lua_Integer n);
void lua_pushlstring(lua_State *L, const char *s, size_t len);
void lua_pushstring(lua_State *L, const char *s);
</div>
上面的函数非常简单,从命名就能知道它们的含义。这里不多说。稍后提供详细的实例代码供参考。由于这个栈并不是无限大的,当向栈中压入一个元素时,应该确保栈中具有足够的空间。当Lua启动时,或Lua调用C语言时,栈中至少会有20个空闲的槽。这些空间一般情况下是足够的,所有我们一般是不用考虑的,但总是会有特殊情况的,如果调用一个具有很多参数的函数,就需要调用lua_checkstack来检查栈中是否有足够的空间。

查询元素

API 使用索引来栈中的元素。第一个压入栈中的元素索引为1,第二个压入的元素所以为2,以此类推,直到栈顶。我们也可以用栈顶作为参考物,使用负数来访问栈中的元素,此时,-1表示栈顶元素,-2表示栈顶下面的元素,以此类推。有的情况适合使用正数索引,而有的情况下适合使用负数索引,我们可以根据实际需求,灵活变通。

为了检查一个元素是否为特定的类型,API提供了一系列的函数lua_is*,其中*可以是任意Lua类型。这些函数有lua_isnumber、lua_isstring和lua_istable等,所有这些函数都有同样的原型:

int lua_is*(lua_State *L, int index);
</div>
实际上,lua_isnumber不会检查值是否为数字类型,而是检查值是否能转换为数字类型。lua_isstring也具有同样的行为,这样就出现一种状况,对于能转换成string的值,lua_isstring总是返回真,所以lua_is*这类函数在使用的时候,并不是非常的方便,所以,就出现了一个lua_type函数,它会返回栈中元素的类型,每种类型都对应一个常亮,这些常亮定义在头文件lua.h中,它们是:
/*
** basic types
*/
#define LUA_TNONE        (-1)
#define LUA_TNIL        0
#define LUA_TBOOLEAN        1
#define LUA_TLIGHTUSERDATA    2
#define LUA_TNUMBER        3
#define LUA_TSTRING        4
#define LUA_TTABLE        5
#define LUA_TFUNCTION        6
#define LUA_TUSERDATA        7
#define LUA_TTHREAD        8
</div>

如果要检查一个元素是否为真正的字符串或数字(无需转换),也可以使用这个函数。

取值

我们一般使用lua_to*函数用于从栈中获取一个值,有以下常用的取值函数:

您可能想查找下面的文章:

  • Lua编程示例(七):协同程序基础逻辑
  • 使用Lua作为C语言项目的配置文件实例
  • C语言中调用Lua函数实例
  • C语言模块回调Lua函数的两种方法
  • Lua与C语言间的交互实例
  • C语言中通过LUA API访问LUA脚本变量的简单例子
  • Lua和C语言的交互详解

相关文章

  • 基于 aLi Lua Web Server 的一个简单例子
  • Lua中变相实现continue跳出循环
  • Cocos2d-x中调用Lua及HelloWorld.lua源码分解
  • 把Lua函数传递到C/C++中实例
  • Lua中ipair和pair的区别
  • Lua性能优化技巧(六):最后的提示
  • lua+love2d制作的2048游戏
  • Lua的迭代器使用中应该避免的问题和技巧
  • Lua中的string库(字符串函数库)总结
  • Lua教程(二十一):编写C函数的技巧

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • Lua中的逻辑运算符使用详解
    • Lua获取utf8字符串长度和字符串截取并用...代替
    • Lua的协程(coroutine)简介
    • C语言中调用Lua函数实例
    • Lua中模块以及实现方法指南
    • Lua编程示例(五): C语言对Lua表的读取和添加
    • Lua中的操作符和表达式总结
    • Lua教程(十一):模块与包详解
    • Lua获取网络时间(获取时间同步服务器的时间)
    • 简单讲解Lua中的垃圾回收机制

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有