C语言API总览

本文深入探讨了C语言与Lua之间的交互,包括如何使用C API创建和管理Lua状态,处理错误,以及栈操作。文章通过示例介绍了luaL_newstate、luaL_openlibs、luaL_loadstring和lua_pcall等关键函数的用法,并阐述了栈在二者通信中的重要角色。同时,讨论了内存分配策略和错误处理方法,强调了lua_error和lua_pcall在错误管理中的作用。
摘要由CSDN通过智能技术生成

文章新地址


    Lua是一种嵌入式语言,这就意味着Lua并不是一个独立运行的应用,而是一个库,它可以链接到其他应用程序,将Lua的功能融入这些应用。
    因为能够当作库来扩展某个应用程序,所以Lua是一种嵌入式语言。同时,使用了Lua语言的程序也可以在Lua环境中注册新的函数,比如用C语言实现函数,从而增加一些无法直接用Lua语言编写的功能。因此Lua也是一种可扩展的语言。
    上述两种对Lua语言的定位分别对应C语言和Lua语言之间的两种交互形式。在第一种形式中,C语言拥有控制权,而Lua语言被用作库,这种交互形式中的C代码被称为应用代码。在第二种形式中,Lua语言拥有控制权,而C语言被用作库,此时的C代码被称为库代码。应用代码和库代码都适用相同的API与Lua语言通信,这些API被称为C API。
    C API是一个函数、常量和类型组成的集合,有了它,C语言代码就能与Lua语言交互。C API包括读写Lua全局变量的函数、调用Lua函数的函数、运行Lua代码段的函数,以及注册C函数的函数等。通过调用CAPI,C代码几乎可以做Lua代码能够做的所有事情。
    CAPI遵循C语言的操作模式,与Lua的操作模式由很大的区别。在使用C语言编程时,我们必须注意类型检查、错误恢复、内存分配错误和其他一些复杂的概念。CAPI中的大多数函数都不会检查其参数的正确性,我们必须在调用函数前确保参数的合法性,一旦出错,程序会直接崩溃而不会收到规范的错误信息。此外,CAPI强调的是灵活性和简洁性,某些情况下会以牺牲易用性为代价,即便是常见的需求,也可能需要调用好几个API。这么做虽然有些繁琐,但我们却可以完全控制所有细节。

第一个示例

    首先来学习一个简单的应用程序的例子:一个独立的解释器。

一个简单地额独立解释器

#include <stdio.h>
#include <string.h>
#include "lua.h"
#include "luaxlib.h"
#include "lualib.h"

int main(void){
   
	char buff[256];
	int error;
	lua_State *L = luaL_newstate();     /*打开Lua*/
	luaL_openlibs(L);				/*打开标准库*/

	while (fgets(buff,sizeof(buff),stdin)!= NULL){
   
		error = luaL_loadstring(L,buff)||lua_pcall(L,0,0,0);
		if(error){
   
			fprintf(stderr,"%s\n",lua_tostring(L,-1));
			lua_pop(L,1);			/*从栈中弹出错误信息*/
		}
	}
	lua_close(L);
	return 0;
}

    头文件lua.h声明了Lua提供的基础函数,其中包括创建新Lua环境的函数、调用Lua函数的函数、读写环境中的全局变量的函数,以及注册供Lua语言调用新函数的函数等等。lua.h中声明的所有内容都有一个前缀lua_。
    头文件luaxlib.h声明了辅助库所提供的函数,其中所有的声明均以luaL_开头。辅助库使用lua.h提供的基础API来提供更高层次的抽象,特别是对标准库用到的相关机制进行抽象。基础API追求经济性和正交性,而辅助库则追求对常见任务的实用性。当然,要在程序中创建其他所需的抽象也是非常简单的。请记住,辅助库不能访问Lua的内部元素,而只能通过lua.h中声明的官方基础API完成所有工作。辅助库能实现什么,你的程序就能实现什么。
    Lua标准库没有定义任何C语言全局变量,它将其所有的状态都保存在动态的结构体lua_State中,Lua中的所有函数都接收一个指向该结构的指针作为参数。这种设计使得Lua是可重入的,并且可以直接用于编程多线程代码。
    顾名思义,函数luaL_newstate用于创建一个新的Lua状态。当它创建一个新状态时,新环境中没有包含预定义的函数,甚至连print也没有。为了保持Lua语言的精炼,所有的标准库都被组织成不同的包,这样我们在不需要使用某些包时可以忽略它们。头文件lualib.h中声明了用于打开这些库的函数。函数luaL_openlibs用于打开所有的标准库。
    当创建好一个状态并且在其中加载标准库以后,就可以处理用户的输入了。程序会首先调用函数luaL_loadstring来编译用户输入的每一行内容。如果没有错误,则返回零,并向栈中压入编译后得到的函数。然后,程序调用函数lua_pcall从栈中弹出编译后的函数,并以保护模式运行。与函数lua_loadstring类似,如果没有错误发生,函数lua_pcall则返回零;当发生错误时,这两个函数都会向栈中压入一条错误信息。随后我们可以通过函数lua_tostring获取错误信息,并在打印错误信息后使用函数lua_pop将从栈中删除。
    在C语言中,真是的错误处理可能会相当复杂,并且如何处理错误取决于应用的性质。Lua核不会直接向任何输出流写入数据,它只会通过返回错误信息来提示错误。每个应用可以用其所需的最恰当的方式来处理这些错误信息。为了简化讨论,假设一下示例使用如下简单的错误处理函数,即打印一条错误信息,关闭Lua状态并结束整个应用:

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
void error (lua_State *L,const char *fmt, ...){
   
	va_list argp;
	va_start(argp,fmt);
	vfprintf(stderr,fmt,argp);
	va_end(argp);
	lua_close(L);
	exit(EXIT_FAILURE);
}

    由于Lua既可以作为C代码来编译,也可以作为C++代码来编译,因此lua.h中并没有包含以下这种在C标准库中的常见的写法:

#ifdef __cplusplus
extern "C"{
   
	#endif
	...
	#ifdef __cplusplus
}
#endif

如果将Lua作为C代码编译出来后又要在C++中使用,那么可以引入lua.hpp来替代lua.h,定义如下:

extern 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平淡风云

您的打赏是我继续创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值