Lua教程(十七):C API简介

论坛 期权论坛 脚本     
niminba   2021-5-23 03:55   1812   0

Lua是一种嵌入式脚本语言,即Lua不是可以单独运行的程序,在实际应用中,主要存在两种应用形式。第一种形式是,C/C++作为主程序,调用Lua代码,此时可以将Lua看做“可扩展的语言”,我们将这种应用称为“应用程序代码”。第二种形式是Lua具有控制权,而C/C++代码则作为Lua的“库代码”。在这两种形式中,都是通过Lua提供的C API完成两种语言之间的通信的。

1. 基础知识:

C API是一组能使C/C++代码与Lua交互的函数。其中包括读写Lua全局变量、调用Lua函数、运行一段Lua代码,以及注册C函数以供Lua代码调用等。这里先给出一个简单的示例代码:

复制代码 代码如下:

#include <stdio.h>
#include <string.h>
#include <lua.hpp>
#include <lauxlib.h>
#include <lualib.h>

int main(void)
{
    const char* buff = "print(\"hello\")";
    int error;
    lua_State* L = luaL_newstate();
    luaL_openlibs(L);

    error = luaL_loadbuffer(L,buff,strlen(buff),"line") || lua_pcall(L,0,0,0);
    int s = lua_gettop(L);
    if (error) {
        fprintf(stderr,"%s",lua_tostring(L,-1));
        lua_pop(L,1);
    }
    lua_close(L);
    return 0;
}


下面是针对以上代码给出的具体解释:

    1). 上面的代码是基于我的C++工程,而非C工程,因此包含的头文件是lua.hpp,如果是C工程,可以直接包含lua.h。
    2). Lua库中没有定义任何全局变量,而是将所有的状态都保存在动态结构lua_State中,后面所有的C API都需要该指针作为第一个参数。
    3). luaL_openlibs函数是用于打开Lua中的所有标准库,如io库、string库等。
    4). luaL_loadbuffer编译了buff中的Lua代码,如果没有错误,则返回0,同时将编译后的程序块压入虚拟栈中。
    5). lua_pcall函数会将程序块从栈中弹出,并在保护模式下运行该程序块。执行成功返回0,否则将错误信息压入栈中。
    6). lua_tostring函数中的-1,表示栈顶的索引值,栈底的索引值为1,以此类推。该函数将返回栈顶的错误信息,但是不会将其从栈中弹出。
    7). lua_pop是一个宏,用于从虚拟栈中弹出指定数量的元素,这里的1表示仅弹出栈顶的元素。
    8). lua_close用于释放状态指针所引用的资源。

    2. 栈:

    在Lua和C语言之间进行数据交换时,由于两种语言之间有着较大的差异,比如Lua是动态类型,C语言是静态类型,Lua是自动内存管理,而C语言则是手动内存管理。为了解决这些问题,Lua的设计者使用了虚拟栈作为二者之间数据交互的介质。在C/C++程序中,如果要获取Lua的值,只需调用Lua的C API函数,Lua就会将指定的值压入栈中。要将一个值传给Lua时,需要先将该值压入栈,然后调用Lua的C API,Lua就会获取该值并将其从栈中弹出。为了可以将不同类型的值压入栈,以及从栈中取出不同类型的值,Lua为每种类型均设定了一个特定函数。

    1). 压入元素:

    Lua针对每种C类型,都有一个C API函数与之对应,如:
 

复制代码 代码如下:

    void lua_pushnil(lua_State* L);  --nil值
    void lua_pushboolean(lua_State* L, int b); --布尔值
    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);  --以零结尾的字符串,其长度可由strlen得出。
 


    对于字符串数据,Lua不会持有他们的指针,而是调用在API时生成一个内部副本,因此,即使在这些函数返回后立刻释放或修改这些字符串指针,也不会有任何问题。
    在向栈中压入数据时,可以通过调用下面的函数判断是否有足够的栈空间可用,一般而言,Lua会预留20个槽位,对于普通应用来说已经足够了,除非是遇到有很多参数的函数。
    int lua_checkstack(lua_State* L, int extra) --期望得到exs#Тfffffff&""#Тfff'#Тfff&%"#Ч'#УFcУG&f2[nZi8X{[7G&У'7ffNKnK{X{yNi[hKNhX{[KZInyD2KnK{NyJKhNiX{[.#Тfb6736F#6736WB"FFsSsSb"C6WCsSsSb#nK>zS7K>zZh.KFcb6736C6SsSb##ТfffFVFRjKX>{JyNKi[8##ТffffFVFR[njnKhZN{J.[X ##ТfffffRFR[nhZJ.[yNXX>{JXXZ^j8##ТffffFRXNhZJ.[KyNXX>{JnKyNXX>{JzXKz{8##ТffffW'BFR[njnXX>{JhX[X Y yNK{8##Тffff6RFR[X{jnXX>{Jn[nXhZJ.[K8##ТfFc#ТfffKnKKZJKX{hZ[x>{J#Уb6736F#6736WB"FFScCb"C6WCScCb#nK>zS7K>zZh.KFcb6736C6ScCb#VfFfffFc#ТfffxZh.KzKK>z#Уb6736F#6736WB"FFc#S3B"C6WCc#S3B#nK>zS7K>zZh.KFcb6736C6#S3B##Ц#Ч#ТfffFR7FFR#Тfff&#Тfff&W"#Тfff#Тfff7G&&V#Тfff7F6GVVRvV'7fffR#Тfff7F6GVVRvV'VSУ'7ff6R2#Тfff7F6GVVRG'VRvVУ'7ffF#Тfff7F6GVVRG'VRvVУ'7ff#Тfff7F6GVVRG'VRУ'7ffFR#Тfff7F6GVVSУ'7ff6R#Тfff&WGW&#Ч'#УFcУG&2KNIyn7G&УG&fffz[K>zyNIyn7G&У'7ff [h8^Xk^KNyJz[izK( [yN8.Yj4X( h^ZKk>( I; yJ( J~h ^( {[i yz[Y{>i[NyJz[h~Xiz[{yN( J~h ^( {[8.Zh.i[NyJz[YXIKX{~>yJX{[K^Kj[K>z8.XhXh^ZIKKKIzn[nz>xYxKK{NyNxnh8.Zh.ihKKyD>K>zX{[>[nhK>X{[KKXnY>yJ>X{[8##Тffff#УG&fff"V>yJ>z[7G&У'7ff [>KK*>yJyD>X{[j8kXXI>[ [NyJi[Kk^ydKihk^ynyNXNknY>Y[~h~N*>KnNKKiIh

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1060120
帖子:212021
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP