#Lua#The Stack

欢迎前往个人博客 驽马点滴 和视频空间 哔哩哔哩-《挨踢日志》


这几天重看 Programming in Lua,介绍了 The Stack的概念,中文有很多翻译:Lua堆栈、Lua状态……我倾向于不翻译,称之为:The Stack.

这篇主要主要讲的是:为什么会出现 The Stack 这样的一个模型,用来作为数据交互的一个重要媒介

对于一个功能的出现,常常先有需求,然后实现。

提出需求应该是这样的:我们想编写一门XX类型的语言,希望它具有YY的特性,能够实现ZZ的功能。

在讲述The Stack之前,首先我们要明确一些前置概念:
要设计Lua语言,它包含的一些重要部分有:

  1. 脚本语言的语法规则
  2. 解释器
  3. C API

它的流程是这样的:编写脚本helloworld.lua
解释器负责将local a = 5 这样的脚本语言转化为调用C API,完成脚本语言到C语言之间的调用转化。
于是 脚本中的调用 就等价于 C API的调用,因此,所谓脚本的特性,就要求C API这套机制必须拥有这些特性。
于是给出了问题的转换:**定义脚本语言Lua,就是定义 C API **

现在回到需求本身,有了这样的一个需求以后,当我们尝试在Lua(即C API)和C之间进行数据交互的时候,可能会遇到哪些问题呢?

  1. Lua是一门动态语言,而C是一门静态语言,产生了动态语言与静态语言不匹配的问题;
  2. Lua是自动内存管理,而C是手动内存管理,产生了内存管理机制不匹配的问题;

让我们更具体的来描述这些问题:

当我们在脚本中输入

a[k] = v

k和v都可以有多种数据类型,甚至a也可以有多种类型(取决于其元表),我们希望这样的表达式经过解释器翻译后,通过调用C API就能实现这个功能,那么如何处理呢?
由于C是一门静态语言,当我们试图提供这样的一个赋值操作比如:settable,这个函数的原型是固定的,参数类型是固定的。因此为了实现上述的赋值操作,我们需要定义上百个这样的函数。

void lua_settable_1(int a[], int k, int v)
void lua_settable_2(double a[], int k, double v)
......

这显然是无法接受的。

一个直观的解决方案,是定义一个C中的 union 类型,比如说 lua_Value

void lua_settable(lua_Value a, lua_Value k, lua_Value v)

这样的解决方案带来两个问题:

  1. 当我们尝试在其他编程语言中去做变量的映射关系时,这种复杂的类型的映射就变得相当困难了,而我们设计 C API的时候,希望它不限于C/C++,而是能够与更多的语言进行转换;

  2. 我们希望为Lua设计垃圾回收机制,如果我们用C变量来持有一个Lua table,那么Lua引擎将无从判断这个C变量的使用情况,很可能错误的将其当做垃圾而回收。

于是,Lua 提供了 The Stack 进行数据之间的交互。

当需要获取某个变量值的时候,调用C API,它会将所需要的数据压入The Stack,放在栈顶,然后再次调用C API,从The Stack中获取该数据。

接下去的文章里,会讲述C API提供了怎样一套机制。

你可能感兴趣的:(#Lua#The Stack)