Lua与C/C++的交互

学习提速专享!AI工具全家桶免费用 限时购周边加赠Coding Plan Lite,解锁20+主流AI工具,写代码、查资料快人一步! 阅读详情

转载自http://blog.chinaunix.net/uid-571104-id-2734746.html


Lua5.1的常用API
    lua_State
            Lua状态机或叫Lua虚拟机,支持多线程,可创建多个状态机
    typedef int (*lua_Cfunction)(lua_State* L)
            Lua所调用的C函数的函数原型,在C程序中需要将这种函数类型的
            函数注册到Lua状态机中,此后Lua才能调用到C的函数
            如果有函数
            int c_Hello(lua_State* l)
            {
               luaL_checktype(l, 1, LUA_TSTRING)
               luaL_checktype(l, 2, LUA_TSTRING)    // 两个参数都是字符串
                // 先输出第二个参数,后输出第一个参数
             printf("%s\t%s\n", lua_tostring(l,-1), lua_tostring(l, -2));
      }

            需在C程序初始化的时候执行以下代码:
                    // 将函数名压入LuaVM栈
                    lua_pushstring(l, "c_hello");
                    // 将函数地址压入LuaVM栈
                    lua_pushcclosure(l, &c_Hello, 0)
                    // 把LuaVM栈上的这个表放入全局表中
                    lua_settable(l, LUA_GLOBALSINDEX)
            此后在Lua中就可以这样调用:
                    c_hello()

            注:C函数的实现如果有参数的话最好为每一个参数进行类型检查
                    以确保所栈里的参数是函数参数类型匹配

    lua_State* lua_newstate(lua_Alloc f, void* ud)
            新建一个LuaVM,可以直接调用lua_open来调用这个函数

    void lua_close(lua_State* l))
            关闭LuaVM


    关于栈帧
            当一个函数调用发生的时候就形成了一个栈帧,当这个函数调用结束
            后这个栈帧就消失了

            如在Lua这样调用c_hello("Hello", "World"),那么c_Hello所看到
            栈帧就是从它的参数开始,如下图:
            可以有两种索引方式对栈顶进行操作,正数和负数。    



    栈相关操作
             int  (lua_gettop )  (lua_State  *L )
                    取得当前使用了多少栈空间
            void  (lua_settop )  (lua_State  *L ,  int idx )
                    把栈顶设置在idx处,相当于做了一次函数调用改变了栈帧
                    如果这个时候调用 lua_settop (L , 1 ),则会把刚压入栈的两个参数删除
            void  (lua_pushvalue )  (lua_State  *L ,  int idx )
                    向此栈帧的第idx个位置的值压入栈顶,相当于复制
            void  (lua_remove )  (lua_State  *L ,  int idx )
                    删除第idx个位置的值
                    如果lua_remove (L ,  -2 )则会将 "Hello"删除而剩下 "World"在栈顶
                    并会被移到原来 "Hello"存放的位置
            void  (lua_insert )  (lua_State  *L ,  int idx ) ;
                    先将整个上移或下移,并将栈顶的值压入空出的位置
            void  (lua_replace )  (lua_State  *L ,  int idx )
                    把栈顶的值替换掉idx处的值
             int  (lua_checkstack )  (lua_State  *L ,  int sz )
                    检查栈的大小是否已经增长到最大值,如果没有则将栈的大小增长sz
                    返回0表示栈溢出,返回1表示成功
            void  (lua_xmove )  (lua_State  *from , lua_State  *to ,  int n )
                    从LavVM的栈顶移动n个值到to的LuaVM的栈顶


    栈存取操作
            以下函数往栈顶压入一个C值
            void  (lua_pushnil )  (lua_State  *L )
                    往栈顶压入一个NIL值
            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 l )
                    往栈顶压入一个二进制串
            void  (lua_pushstring )  (lua_State  *L , const char  *s )
                    往栈顶压入一个字符串
            const char  * (lua_pushvfstring )  (lua_State  *L , const char  *fmt , va_list argp )
                    往栈顶压入一个格式化串,不过argp是变参
            const char  * (lua_pushfstring )  (lua_State  *L , const char  *fmt ,  . . . )
                    往栈顶压入一个格式化串
            void  (lua_pushcclosure )  (lua_State  *L , lua_CFunction fn ,  int n )
                    压入一个函数
            void  (lua_pushboolean )  (lua_State  *L ,  int b )
                    往栈顶压入一个bool类型
            void  (lua_pushlightuserdata )  (lua_State  *L , void  *p )
                    往栈顶压入一个数组,数组的内存块指向p
             int  (lua_pushthread )  (lua_State  *L )


            以下函数往从栈中复制一个值存入栈顶
            void  (lua_gettable )  (lua_State  *L ,  int idx )
                    idx指向表在栈中的位置,弹出栈顶的key取得表中的值并压入栈顶
                    此函数与lua_rawget的区别在于此函数会调用metatable的方法
            void  (lua_getfield )  (lua_State  *L ,  int idx , const char  *k )
                    以k所在栈中的索引 (idx )作为参数,取得k对应的值并压入栈顶
                    效率与lua_gettable相同
            void  (lua_rawget )  (lua_State  *L ,  int idx )
                    idx指向表在栈中的位置,弹出栈顶的key取得表中的值并压入栈顶
                    为了提高数据访问的效率而直接读取表中的数据,不需要对metamethod的调用
                    这个函数在循环访问数组元素比较方便
            void  (lua_rawgeti )  (lua_State  *L ,  int idx ,  int n )
                    idx指向表在栈中的位置,n指向key在栈中的位置,取得表中的值并入栈
                    相当于 :lua_pushnumber (L ,n ) ; lua_rawget (L ,idx )
            void  (lua_createtable )  (lua_State  *L ,  int narr ,  int nrec )
                    新建一个表并压入栈顶,表的大小为narr,并预留了nrec个元素空间
            void  * (lua_newuserdata )  (lua_State  *L , size_t sz )
                    在栈中分配一块大小为sz的内存并把管理结构入栈且返回内存地址
             int  (lua_getmetatable )  (lua_State  *L ,  int objindex )
                    objindex指向对象在栈中的位置,取得对象的metatable并将其压入栈顶
                    如果失败或者对象没有metatable表则返回0
            void  (lua_getfenv )  (lua_State  *L ,  int idx )
                    idx指向对象所在栈中的位置,取得此对象并将其环境量压入栈

            以下函数用于判断栈内某处值的类型
             int  (lua_isnumber )  (lua_State  *L ,  int idx )
                    栈idx处的值是否是实数
             int  (lua_isstring )  (lua_State  *L ,  int idx )
                    栈idx处的值是否是字符串
             int  (lua_iscfunction )  (lua_State  *L ,  int idx )
                    栈idx处的值是否是函数
             int  (lua_isuserdata )  (lua_State  *L ,  int idx )
                    栈idx处的值是否是二进制数据
             int  (lua_type )  (lua_State  *L ,  int idx )
                    取得栈idx处的值的类型
            const char  * (lua_typename )  (lua_State  *L ,  int tp )
                    将类型转换成C字符串
             int  (lua_equal )  (lua_State  *L ,  int idx1 ,  int idx2 )
                    栈内两个值是否相等,类型和值都需要相等才返回真
             int  (lua_rawequal )  (lua_State  *L ,  int idx1 ,  int idx2 )
                    栈内两个对象是否相等,如果是对象时所指对象相同也算相等
             int  (lua_lessthan )  (lua_State  *L ,  int idx1 ,  int idx2 )
                    栈内两个值的大小 ,idx1处的值是否小于idx2处的值

            以下函数将栈内的某个格转换成C能理解的值,栈结构不变
            lua_Number  (lua_tonumber )  (lua_State  *L ,  int idx )
                    将idx所指向的Lua值转换成实数返回
            lua_Integer  (lua_tointeger )  (lua_State  *L ,  int idx )
                    将idx所指向的Lua值转换成整数返回
             int  (lua_toboolean )  (lua_State  *L ,  int idx )
                    将idx所指向的Lua值转换成bool值返回
            const char  * (lua_tolstring )  (lua_State  *L ,  int idx , size_t  *len )
                    将idx所指向的Lua值转换成字符串返回,并把长度存入len中
            size_t  (lua_objlen )  (lua_State  *L ,  int idx )
                    取得idx所指向的Lua值长度
            lua_Cfunction  (lua_tocfunction )  (lua_State  *L ,  int idx )
                    将idx所指向的Lua值转换成函数返回
            void  * (lua_touserdata )  (lua_State  *L ,  int idx )
                    将idx所指向的Lua值转换成内存块 (数组 )返回
            lua_State  * (lua_tothread )  (lua_State  *L ,  int idx )
                    将idx所指向的Lua值转换成LuaVM对象返回
            const void  * (lua_topointer )  (lua_State  *L ,  int idx )
                    取得idx所指对象的值的存储地址返回

            以下函数与其对应的get函数类似
            void  (lua_settable )  (lua_State  *L ,  int idx )
            void  (lua_setfield )  (lua_State  *L ,  int idx , const char  *k )
            void  (lua_rawset )  (lua_State  *L ,  int idx )
            void  (lua_rawseti )  (lua_State  *L ,  int idx ,  int n )
             int  (lua_setmetatable )  (lua_State  *L ,  int objindex )
             int  (lua_setfenv )  (lua_State  *L ,  int idx )

    函数调用
      关于函数调用
          当需要调用一个Lua函数时,先要将函数压入栈中,然后将其参数依次压入
            如下图:

             假设在Lua代码中有函数 :
                function hello ( x , y )
                   print ( x , y )
                end
                则在C中可以这样来调用 :
               lua_getglobal (L ,  "hello" ) ;  - - 从全局域中取得hello函数并压入栈顶
                lua_pushstring (L ,  "Hello" ) ;  - - 依次压入两个参数
               lua_pushstring (L ,  "World" ) ;    
                lua_call (L , 2 , 0 ) ;  - - 跳过两个参数取得函数并调用此函数 ,函数中会取得相应参数
                                    
            void  (lua_call )  (lua_State  *L ,  int nargs ,  int nresults )
                    无保护的函数调用
                    nargs是指调用函数的参数个数,nresults是指所调用的函数的返回值个数
             int  (lua_pcall )  (lua_State  *L ,  int nargs ,  int nresults ,  int errfunc )
                    与lua_call相似,不过此函数是在保护模式下被调用
                    如果发生错误则会将错误压入栈,否则功能与lua_call一样
             int  (lua_cpcall )  (lua_State  *L , lua_CFunction func , void  *ud )
                    直接调用一个C函数,并把ud做为func函数调用的参数
                    也就是说在func函数内部看来第一个参数是ud
             int  (lua_load )  (lua_State  *L , lua_Reader reader , void  *dt , const char  *chunkname ) ;
lua和c/c++交互 lua 和c采用虚拟栈的方式传递数据,栈中的元素是以lua 数据结构的方式存储, 阅读详情

相关推荐

Lua常用C APIC/C++交互

Lua handles a chunk as the body of an anonymous function with a variable number of arguments”这是Lua对chunk也就是lua文件的处理方式,就是认为是一个可变参数的匿名函数。也就是说,调用后栈上有一个匿名函数,这个函数的body就是文件中所有的内容。

悦分享 1201

lua-5.1.4中文离线API文档

中文版lua api手册 需要的可以下载,中文版lua api手册 需要的可以下载

LuaC/C++动态链接库交互示例

Lua的名称源于葡萄牙语“Lua”,意为“月亮”。它由Roberto Ierusalimschy、Waldemar Celes和Luiz Henrique de Figueiredo在巴西里约热内卢的天主教大学共同设计开发。Lua是动态类型语言,支持过程式、面向对象和函数式编程,其小巧的体积(通常小于200KB)和出色的性能使其适合嵌入到应用程序中作为扩展语言。

weixin_32921023的博客 854

LUA5.1的API

LUA5.1的API函数 lua_State* luaL_newstate() Lua脚本的编译执行是相互独立的,在不同的线程上执行。通过luaL_newstate()函数可以申请一个虚拟机,返回指针类型 lua_State。今后其他所有Lua Api函数的调用都需要此指针作为第一参数,用来指定某个虚拟机。

lua 堆栈管理

lua 堆栈介绍_李生龙的博客-CSDN博客_lua

qixiang2013的专栏 1895

Lua的理解

首先是Lua本身,打开5.1的lua版本开始编译后最后生成一个lua的可执行文件,这其实就是一个包含了Lua虚拟机的终端.。所以其实在不管redis也好nginx也好,也是在其中生产了一个Lua环境(虚拟机),然后将nginx里面/redis里面的一些函数暴漏出去,到达在Lua里面操作宿主环境的效果。在宿主中创建完Lua的State后,我们的目的是为了操作宿主里面的东西,所以需要将宿主里面的功能注入到State里面去以便Lua操作。但如何理解Lua以及Lua宿主环境的交互是需要掌握的。

u012566181的专栏 631

Lua_第26章撰写 C 函数的技巧

26.1 数组操作 26.2 字符串处理 26.3 在 C 函数中保存状态 The Registry References Upvalues Lua 全局变量可以存放任何类型的 Lua 值,并且每一个独立的状态都有他 自己独立的全局变量集。然而,并不是在所有情况下,这种方法都是令人满意地解决方案,因为 Lua 代码可能会修改这些全局变量,危及 C 数据的完整性。为了避免这个问题, Lua 提供了一个独立的被称为 registry 的表,C 代码可以自由使用,但 Lua 代码不能访问他。

heyuchang666的专栏 4670

Lua 5.1 参考手册

Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes云风 译 www.codingnow.com Copyright © 2006 Lua.org, PUC-Rio. All rights reserved.  1 - 介绍Lua 是一个扩展式程序设计语言

wangchuanjin的专栏 1191

lua堆栈操作

(1)luaC++之间的交互的基本知识:      luaC++ 之间的数据交互通过堆栈进行,栈中的数据通过索引值进行定位,(栈就像是一个容器一样,放进去的东西都要有标号)其中栈顶是-1,栈底是1,也就是第 1 个入栈的在栈底;也可以这么说:正数表示相对于栈底的位置(位移),负数表示相对于栈顶的位置(位移);(2)计算和清空栈中元素的操作:1、函数lua_gettop()用于返回栈

lovemysea的专栏 2万+

LuaC/C++交互——C/C++调用Lua脚本

LuaC/C++交互——C/C++调用Lua脚本

牧秦丶 8883

Lua封装&C++实践(一)——Lua和C/C++的基本交互

Lua 是一个小巧的脚本语言,它本身就是作为嵌入脚本而设计的,在目前所有脚本引擎中,Lua的速度是最快的。而且它的解释器非常轻量,其解释器不过200k(不同版本可能略有差异)。 Lua项目包含许多技术点,花些时间研究可以有不少收获,学到很多东西。包括宿主语言的交互、内存管理、虚拟机实现、协程、闭包、异常捕获机制等等,后续有时间慢慢研究下。 如题所示,本系列主要记录Lua封装相关笔记,主要是记录C...

偶尔记录的一些学习笔记 3094

Lua中的table数据类型及其C/C++交互

table是Lua中唯一的数据结构机制,它实现了关联数组(associative arrays),可以用于表示普通数组、序列、符号表、集合、记录、图、树等多种数据结构。

weixin_42849849的博客 1172

Lua之·LuaC/C++交互·Lua CAPI访问栈操作】

Lua是一种轻量级的、高性能的脚本语言,经常被用于游戏开发、嵌入式系统和其他需要灵活、可扩展的脚本功能的应用程序中。Lua是一种解释型语言,它具有简单的语法和动态类型系统,使得它易于学习和使用。它的设计目标是成为一种嵌入式脚本语言,在C/C++程序中作为库使用。这使得Lua非常适用于游戏开发,因为它可以其他编程语言结合使用,提供灵活的脚本功能。Lua的另一个重要特点是它的高性能。其他动态语言相比,Lua的执行速度非常快,这得益于它的精简设计和高度优化的虚拟机。

m0_66203017的博客 1944

C/C++Lua交互

<br />C/C++Lua交互 <br />一、C/C++调用Lua<br />注意点<br />1、extern "C"<br />2、luaL_openlibs(L)<br />3、luaL_dofile(L, "test.lua")<br />cpp文件:<br />#include <stdio.h><br />//Since the static Lua libraries are written in C, you must import them as such: <br />exter

liuchang5的专栏 1887

C/C++编程:LuaC/C++交互

Lua是一门动态脚本语言,运行依托于宿主语言,可以是C、C++、C#、golang等,只要实现了Lua解释器就可以。所以,Lua从设计来讲就是动态脚本语言,正是因为它是解释性语言,所以它更充当了这些宿主语言的“缝合”作用,是为“胶水”性语言 准备 在Linux系统安装Lua,使用下面的命令下载并生成Lua程序: $ wget http://www.lua.org/ftp/lua-5.2.3.tar.gz $ tar zxf lua-5.2.3.tar.gz $ cd lua-5.2.3 $ make lin

OceanStar的博客 956

C/C++lua交互

lua,C/C++,交互,stack

zcl1804742527的博客 489

LuaC/C++交互函数问题

初学lua,遇到注册C/C++交互函数问题 在luaC/C++交互时,C/C++的注册Lua函数若是一个有返回类型(压栈)而不是获取类型的时候应该返回1而不是返回0,否则会出现在Lua中值为nil(空) 不太明白为什么事这样,如果有知道的大神,麻烦讲解下 如: 应该是 1 2 3 4 5 6

whChina(江城老温) 1392

搭建LuaC/C++交互的环境

其他luaC交互的函数可以查阅lua手册,进行使用。

weixin_57023347的博客 515
上一篇: 初学者必看:Lua入门学习教程
下一篇: OpenGL入门学习
xiang_521
博客等级 码龄15年 30粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值