Lua设计小巧很容易与C/C++进行交互,下面我们具体讲解C/C++中如何调用lua,而lua中又如何调用C代码.

首先lua和C交互的一个重要的数据结构lua_State,它是进行数据交换的堆栈,按照严格的LIFO规则(后进先出,始终存取栈顶),lua提供了一些函数来压栈例如:
void   (lua_pushnil) ( lua_State *L );
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 );
从函数名称我们可以看出我们可以向栈中压入nil, number, integer, string等类型.
lua还提供了函数,对堆栈进行插入,删除等操作例如:
int    (lua_gettop) ( lua_State *L );
void   (lua_settop) ( lua_State *L , int idx);
void   (lua_pushvalue) ( lua_State *L , int idx);
void   (lua_remove) ( lua_State *L , int idx);
void   (lua_insert) ( lua_State *L , int idx);
void   (lua_replace) ( lua_State *L , int idx);
int    (lua_checkstack) ( lua_State *L , int sz);
函数中的idx参数是数据在栈中的索引,栈中的我们以第一个压入栈中的索引为1,第二个为2,也可以使用负数索引,-1始终表示栈顶的索引,-2表示栈顶下面的第二个元素索引.
lua_gettop函数获取堆栈中元素的个数,也是栈顶元素索引,一个负数索引-x对应于正数索引为gettop-x+1;
lua_settop设置栈顶到指定索引,例如:lua_settop(L, 0)也就是清空堆栈;
lua_remove和lua_insert表示先指定索引插入和删除元素,其他元素作相应移动;
lua_replace从栈顶弹出元素设置到指定的索引位置;
另外我们还可以通过lua_is*一系列函数来检测栈中元素类型,例如:
int  ( lua_isnumber) (lua_State *L, int idx );
int  ( lua_isstring) (lua_State *L, int idx );
int  ( lua_iscfunction) (lua_State *L, int idx );
int  ( lua_isuserdata) (lua_State *L, int idx );
我们可以通过这些函数判断指定索引位置的元素是否是我们期望的类型如:number,string,function等.
好了介绍了这么多函数,我们要实践下写个小程序,实验下各种函数:
#include <stdio.h>
#include <stdlib.h>
 
#ifdef __cplusplus
extern "C" {
#endif
 
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
 
#pragma comment (lib, "lua5.1.lib")
 
#ifdef __cplusplus
}
#endif
 
static int cadd( lua_State *L )
{
    /*lua中调用此函数,参数从栈中弹出 */
    double a = lua_tonumber( L, -2);
    double b = lua_tonumber( L, -1);
 
    lua_pushnumber(L , a + b);
   
    /*返回返回值个数*/
    return 1;
}
 
void load_string (lua_State* L)
{
    /*获取全局变量str,并置于栈顶 */
    lua_getglobal(L , "str");
    if (!lua_isstring (L, -1))
    {
        printf("Get 'str' error, %s\n" , lua_tostring( L, -1));
    }
 
    const char * pstr = lua_tostring(L , -1);
    printf("str : %s\n" , pstr);
   
    /*弹出栈中压入的元素,使栈恢复原来状态 */
    lua_pop(L , 1);
}
 
void load_number (lua_State * L)
{
    /*获取全局变量num,并置于栈顶 */
    lua_getglobal(L , "num");
    if (!lua_isnumber (L, -1))
    {
        printf("Get 'num' error, %s\n" , lua_tostring( L, -1));
    }
 
    double num = lua_tonumber( L, -1);
    printf("num : %lf\n" , num);
   
    lua_pop(L , 1);
}
 
void load_table (lua_State * L)
{
    /*获取全局变量data,并置于栈顶 */
    lua_getglobal(L , "data");
 
    const char * szkey[4] = { "lua", "ruby" , "python", "perl"};
    printf("data = { " );
 
    for (int i = 0; i < 4; ++ i )
    {
        /*在table 在栈顶时,获取 table中key 所对应的value值 ,首先将key 入栈, 此时table位于栈中索引为 ,*/
        /*然后通过调用gettable将 key对应value 压入栈顶, 最后弹出刚才已经读取的元素 ,此时table 重新成为栈顶元素 */
        lua_pushstring(L , szkey[ i]);
        lua_gettable(L , -2);
        printf(" %s = '%s' " , szkey[ i], lua_tostring (L, -1));
        lua_pop(L , 1);
    }
    printf(" }\n" );
 
    lua_pop(L , 1);
}
 
void call_luafunc (lua_State * L)
{
    /*C中调用lua 函数,首先将 lua函数压入栈顶,然后依次压入函数参数 , 函数参数压入从左到右*/
    lua_getglobal(L , "luaadd");
    lua_pushnumber(L , 10);
    lua_pushnumber(L , 20);
    /*保护模式运行luaadd函数 */
    lua_pcall(L , 2, 1, 0);
 
    printf("call luaadd result sum : %lf\n" , lua_tonumber( L, -1));
    lua_pop(L , 1);
}
 
void callback_cfunc (lua_State * L)
{
    lua_getglobal(L , "cfunc");
    lua_pushnumber(L , 10);
    lua_pushnumber(L , 20);
    lua_pcall(L , 2, 1, 0);
 
    printf("call back cadd result sum : %lf\n" , lua_tonumber( L, -1));
    lua_pop(L , 1);
 
}
 
void printtable (lua_State * L)
{
    lua_getglobal(L , "printtable");
 
    /*这里我们new 了一个table然后设置值 ,在lua 中进行打印 */
    lua_newtable(L );
    lua_pushstring(L , "name");
    lua_pushstring(L , "Tom");
    lua_settable(L , -3);
 
    lua_pushstring(L , "age");
    lua_pushstring(L , "20");
    lua_settable(L , -3);
 
    lua_pcall(L , 1, 0, 0);
}
 
int main (void)
{
    lua_State *L = lua_open();
    luaL_openlibs(L );
 
    /*载入lua 文件*/
    luaL_loadfile(L , "test.lua");
    /*这步很重要(test.lua中的 chunk放入堆栈)*/
    lua_pcall(L , 0, 0, 0);
 
    /*从lua 中读取字符串 */
    load_string(L );
    /*从lua 中读取数字类型 */
    load_number(L );
    /*从lua 中读取表类型 */
    load_table(L );
    /*调用lua 中函数*/
    call_luafunc(L );
    /*从lua 调用C函数 */
    callback_cfunc(L );
    /*在C 中建立一个 lua表类型, 在lua中进行打印输出 */
    printtable(L );
 
    lua_close(L );
    return 0;
}
 
--test.lua
str = "This is a string."
num = 22
data = {lua="lua", ruby="ruby", python="python", perl="perl"}

function luaadd(a, b)
        return a + b
end

function cfunc(a, b)
        --回调C中cadd函数,传递a, b两个参数,从左向右压入
        return cadd(a, b)
end

function printtable(t)
        for key in pairs(t) do
                print(key .. ":" .. t[key])
        end
end

 
一.要在C/C++中调用lua我们首先在C/C++中包含下面头文件,如果是C++程序则需要一个宏来保证,编译器生成的函数名按照C语言规则.
#ifdef __cplusplus
extern "C" {
#endif
 
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
 
#pragma comment (lib, "lua5.1.lib")
 
#ifdef __cplusplus
}
#endif
二.我们在main函数中依次调用了一系列函数打开lua环境, 加载标准lua库,然后我们调用luaL_loadfile函数加载一个lua文件,这里只进行了编译lua文中chunk到一个函数中并未进行调用,下面lua_pcall进行调用执行,这步
非常重要,这步就是调用执行编译生成的函数,否则我们后面的调用均不会成功的.另外lua_pcall是从C/C++中调用lua函数,它运行在保护模式,函数调用出错并不会导致程序崩溃,但会返回错误,还有另外一个函数lua_call运行在
非保护模式下.
三.具体函数功能注释已经写的很清楚了,函数调用时参数入栈出栈操作其实和C函数调用时的概念是一致的,明白C语言函数调用的过程,其实很容易理解.
四.lua和C/C++还可以交互userdata类型数据,各种错误处理等这里不再讲述.

lua与C/C++交互的更多相关文章

  1. Lua与C的交互

    Lua 与 C 的交互 Lua是一个嵌入式的语言,它不仅可以是一个独立运行的程序,也可以是一个用来嵌入其它应用的程序库. C API是一个C代码与Lua进行交互的函数集,它由以下几部分构成: 1.  ...

  2. cocos2d-x lua与c++简单交互

    cocos2d-x lua与c++简单交互 version: cocos2d-x 3.6 本文讲述lua与c++的一些简单交互: lua通过消息方式调用c++无参接口 c++调用lua带参接口 1.通 ...

  3. Lua与C/C++交互问题

    初学lua,遇到注册C/C++交互函数问题 在lua与C/C++交互时,C/C++的注册Lua函数若是一个有返回类型(压栈)而不是获取类型的时候应该返回1而不是返回0,否则会出现在Lua中值为nil( ...

  4. Lua与C++的交互

    这篇文章说的挺详细的:Lua与C++的交互

  5. lua与C/C++交互概要

    转 http://blog.csdn.net/wildfireli/article/details/22307635 Lua生来就是为了和C交互的,因此使用C扩展Lua或者将Lua嵌入到C当中都是非常 ...

  6. 通过lua栈了解lua与c的交互

    lua是如何执行的 其中分析.执行部分都是c语言实现的. lua与c的关系 lua的虚拟机是用c语言实现的,换句话说一段lua指令最终在执行时都是当作c语言来执行的,lua的global表,函数调用栈 ...

  7. Lua脚本和C++交互(一)

    现在,越来越多的C++服务器和客户端融入了脚本的支持,尤其在网游领域,脚本语言已经渗透到了方方面面,比如你可以在你的客户端增加一个脚本,这个脚本将会帮你在界面上显示新的数据,亦或帮你完成某些任务,亦或 ...

  8. Lua基本语法-lua与C#的交互(相当简单详细的例子)

    lua脚本 与 C#的交互 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 Lua And C# -- ...

  9. lua和C++的交互(1)

    /* 以前听的一个故事,当年Java的创造者讲课的时候,一开始先拿一个简单的不能简单的小例子, 不断的扩展,最后成为一个复杂而完美的程序. 一个重要之重要的概念,就是栈.Lua与别的语言交互以及交换数 ...

  10. lua与c的交互(函数专用)

    Lua与C的交互 Lua是一个嵌入式的语言,它不仅可以是一个独立运行的程序,也可以是一个用来嵌入其它应用的程序库. C API是一个C代码与Lua进行交互的函数集,它由以下几部分构成: 1.  读写L ...

随机推荐

  1. Windows Server R2服务器 IIS7 部署MVC3网站

    报错:调用 GetProcAddress 失败,在 ISAPI 筛选器 "C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi ...

  2. (转)HTTP协议(2)

    转自:http://kb.cnblogs.com/page/130970/  作者 :小坦克 当今web程序的开发技术真是百家争鸣,ASP.NET, PHP, JSP,Perl, AJAX 等等. 无 ...

  3. Win2008 R2 IIS7.5+PHP5(FastCGI)+MySQL5环境搭建教程

    现在很多朋友想尝试win2008 r2来跑web服务器,跟win2003相比界面差别有点大,有些人可能不太习惯,不过以后是趋势啊,这里简单分享下,方便需要的朋友 准备篇 一.环境说明: 操作系统:Wi ...

  4. hdu 5646 DZY Loves Partition 二分+数学分析+递推

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5646 题意:将n分成k个正整数之和,要求k个数全部相同:并且这k个数的乘积最大为多少?结果mod 1e^9 ...

  5. 组态王6.55WEB全新发布步骤

    转载请... 算了 估计没有人转..自己留着看 目的: 本教程通过组态王6.55实现一个WEB服务器和一个WEB画面的客户端,总共两个工程.服务器工程名为 Server , 客户点为 Client.S ...

  6. 2014年度辛星css教程夏季版第一节

    CSS是Cascading Style Sheets的缩写,即层叠样式表,它用于表现HTML的样式,即HTML只是去写该网页有哪些内容,至于如何去表现它们,由CSS去定制. ************* ...

  7. 创建第一个UI

    创建一个2D UI 制作UI时,首先要创建UI的"根".在Unity顶部NGUI菜单中选择Create,然后选择2D UI. 创建完成后,在Scene窗口中,NGUI自动生成了一个 ...

  8. selenium各种场景下的启动Firefox

    开始学习selenium时为了启动Firefox可谓费尽周折,在大神的帮助下才堪堪搞定,走出了selenium的第一步:jdk1.8 + selenium_2.46 + Firefox国际版40.0. ...

  9. How To Call Stored Procedure In Hibernate

    How To Call Stored Procedure In Hibernate In this tutorial, you will learn how to call a store proce ...

  10. Seay工具分享

    百度网盘:http://pan.baidu.com/share/home?uk=4045637737&view=share#category/type=0