• C/C++中调用LUA函数(zz)


    http://hi.baidu.com/darkpaladin/blog/item/00468551e6b67e2542a75bb2.html

    [转]C/C++中调用LUA函数

    2007-04-27 11:29

    1 配置工作环境

    a 下载LUA安装包 sf_200472410155.zip

    b 然后,解压用于WIN32下的安装包。放在一个盘的目录下如:C:/LUA50

    c  打开VC++6.0,点击Project下的Setting中将include目录设为C:/LUA50。 并在LIB库中加入lua+lib.lib ,并将C:/LUA50下的Lua+lib.dll ,Lua+lib.lib拷贝到程序当前所在目录

    【( 风舞影天 的说明:来自www.luachina.net

    vc下使用lua都很类似(6.0,2003,2005),如果你能明白一般库的使用,那么想要使用lua很简单
    如果是使用纯的lua库(指不使用第三方库,如luabind,lubplus等),一般你可能会得到三种形式的lua包
    1,从www.lua.org下载的源码包
    2,由别人提供的编译好的lua库包
    3,由别人提供的编译好的lua动态链接库包
    对于第一种包你只需要自己编译出lua库然后就可以象第2种方式一样使用了(实际上第三种包的使用方式只是多了一个步骤)
    如何编译LUA源码呢?解压后打开lua目录的INSTALL文件,里面列出了三个工程
    library: lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c
    lmem.c lobject.c lopcodes.c lp***r.c lstate.c lstring.c
    ltable.c ltm.c lundump.c lvm.c lzio.c
    lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c
    ltablib.c lstrlib.c loadlib.c linit.c
    interpreter: library, lua.c
    compiler: library, luac.c print.c
    library,interpreter,compiler,实际上这三个你只需要第一个library,它是让你能够将LUA嵌入你的程序的库, interpreter是解释器,也就是传说中的lua.exe,可以把它看成一个使用lua库的示例程序,第三个compiler是将lua文本编译成 lua的二进制格式,所以一般来讲,第二和第三个对你来讲都不是特别重要或者根本就不会使用到的。
    要编译出这三个库,你可以打开你的IDE(指VC),然后建三个工程,把每个工程对应的文件加入你建立的对应的工程,然后编译即可生成你库文件(*.lib),lua.exe和luac.exe
    INSTALL中也提到了可以使用luavs.bat来生成,看看这个批处理文件的内容cd src
    cl /O2 /W3 /c /DLUA_BUILD_AS_DLL l*.c
    del lua.obj luac.obj
    link /DLL /out:lua51.dll l*.obj
    cl /O2 /W3 /c /DLUA_BUILD_AS_DLL lua.c
    link /out:lua.exe lua.obj lua51.lib
    cd ..
    如果你能看懂它也就知道其实和上面我说的步骤大同小异了(它生成的是动态链接库而不是静态库),至于有人说找不到cl.exe,那是因为你的环境变量里没 有设置vc的二进制文件目录而导致无法找到cl.exe(只要你安装了VC,那么是肯定会有这个文件的)(作为一个程序,如果不知道环境变量这个东东,我 觉得还是有点悲哀哈)
    好了,现在你有了头文件、库文件(或是动态链接库,而动态链接库除了.dll还会提供一个.lib文件),那么剩下的事情就是如何将LUA嵌入你的程序中了。
    首先是在你使用到LUA函数的地方你肯定要#include ,而实际上lua有三个头文件,lua.h, lualib.h,lauxlib.h,你可以打开这些头文件查看有那些LUA API(lua5.x改变了lua4.x的一些函数名,只不过lua5.0.2使用了一些宏来兼容以前的函数名,而5.1.1则去除掉了这些宏,你可以查 看这些头文件来看那些API函数名已经改掉了,比较常见的是lauxlib.h)
    ps:使用C++的同学别忘了你链接库采用的代码生成方式是C++还是C,因为C++最终会改变其函数名(如lua_open改成 lua_open@4),一般都是选择生成C的代码生成方式,因为不同的C++编译器改变的函数名规则是很可能不同的,至于为什么会改名想想函数重载,具 体的去GOOGLE吧。而如果你编译链接库时采用的是C代码生成方式,别忘了在#include时加上extern "C"
    当然你仅仅包含了头文件是肯定会出现链接错误的,因为在链接的时候无法找到对应函数的代码,而这些代码都包含在静态库文件*.lib中(或是动态链接库的*.dll中),VC中加入链接库文件有两种方式,一是工程里设置,二是使用
    #pragma comment(lib,"****.lib")
    )】
    例一:
    main.cpp
    //--------------------------------------------------
    #include <stdio.h>

    extern "C" {
    #include "lua.h"
    #include "lualib.h"
    #include "lauxlib.h"
    }

    /* LUA接口声明*/
    lua_State* L;

    int main ( int argc, char *argv[] )
    {
    /* 初始化 Lua */
    L = lua_open();

    /*载入LUA库 */
    lua_baselibopen(L);

    /* 运行LUA脚本 */
    lua_dofile(L, "test.lua");

    /* 清除 Lua */
    lua_close(L);

    return 0;
    }

    脚本test.lua:
    用记事本写入以下代码,改扩展名为lua即可
    -- simple test

    print "Hello, World!"
    例2:
    首先用记事本写个Lua文件。

    ----fun.lua--------
    function add ( x, y )
    return x + y
    end

    在前面的教程,调用lua_dofile()将执行脚本。
    本章里,脚本定义为一个函数。
    用lua_dofile()只简单的使这个函数在我们的程序中变为有效。

    LUA的函数可以接收多个参数,并可以返回多种类型的结果,这

    里使用了堆栈。

           为了调用一个LUA函数,我们首先要把函数压栈。
    这个函数的结果由参数决定,所以,我们要调用函数将需要
    lua_call(),调用这个函数之后,返回的结果将在堆栈中存在。

    整个步骤:
    1.用lua_getglobal()把add函数放入堆栈
    2.用lua_pushnumber()把第一个参数压入堆栈
    3.用lua_pushnumber()把第二个参数压入堆栈
    4.用lua_call()调用函数。
    5,现在用lua_tonumber从堆栈头取出结果
    6,最后用lua_pop从堆栈中移除结果值。

    代码:luaadd.cpp
    如果你喜欢用C代替C++,改名为luaadd.c,并且除去
    extern "C"即可
    #include <stdio.h>

    extern "C" {
    #include "lua.h"
    #include "lualib.h"
    #include "lauxlib.h"
    }

    /* the Lua interpreter */
    lua_State* L;

    int luaadd ( int x, int y )
    {
    int sum;

    /* the function name */
    lua_getglobal(L, "add");

    /* the first argument */
    lua_pushnumber(L, x);

    /* the second argument */
    lua_pushnumber(L, y);

    /* call the function with 2
          arguments, return 1 result */
    lua_call(L, 2, 1);

    /* get the result */
    sum = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    return sum;
    }

    int main ( int argc, char *argv[] )
    {
    int sum;
    /* initialize Lua */
    L = lua_open();

    /* load Lua base libraries */
    lua_baselibopen(L);

    /* load the script */
    lua_dofile(L, "add.lua");
    /* call the add function */
    sum = luaadd( 10, 15 );

    /* print the result */
    printf( "The sum is %d\n", sum );

    /* cleanup Lua */
    lua_close(L);

    return 0;
    }
    二:lua中调用c函数
    我们用C/C++创建一个函数并告诉Lua解释器,然后在Lua中调用这个函数并使用函数的返回值。
    定义一个C/C++函数:
    要想C/C++中的函数能被Lua调用,函数定义必须这样:
    代码:typedef int (*lua_CFunction) (lua_State *L);
    也就是说,函数必须以Lua解释器作为参数,并且返回值为int类型。既然Lua解释器作为函数的参数,那么实际上函数可以从栈中取得任意多个参数。下面 我们将看到,返回的整数值代表入栈的值的数目。如果有一个C/C++函数,你想在Lua中调用他,很容易封装一下就可以满足上述要求。
    下面的C++的average函数例子中,可以清楚地看到Lua中调用C/C++函数是如何实现的。
    1. lua_gettop()返回栈顶的下标索引,由于Lua中栈的下标从1开始,这个返回值实际上也就是函数参数的个数。
    2. For循环计算各个参数总和。
    3. Average的参数是通过调用lua_pushnumber()入栈的。
    4. 然后参数之和被入栈。
    5. 最后,函数返回值为2,表明有两个返回值,并且已经入栈。
    函数被定义之后,我们必须告诉Lua编译器他的存在,这在main()函数中,在Lua解释器被初始化,类库加载之后完成的。
    将下面的代码保存为luaavg.cpp,如果你喜欢用C而不是C++,需要保存文件为luatest.c并且把extern去掉。
    #include <stdio.h>
    extern "C" {
           #include "lua.h"
           #include "lualib.h"
           #include "lauxlib.h"
    }
    /* the Lua interpreter */
    lua_State* L;
    static int average(lua_State *L)
    {
           /* get number of arguments */
           int n = lua_gettop(L);
           double sum = 0;
           int i;
           /* loop through each argument */
           for (i = 1; i <= n; i++)
           {
               /* total the arguments */
               sum += lua_tonumber(L, i);
           }
           /* push the average */
           lua_pushnumber(L, sum / n);
           /* push the sum */
           lua_pushnumber(L, sum);
           /* return the number of results */
           return 2;
    }
    int main ( int argc, char *argv[] )
    {
           /* initialize Lua */
           L = lua_open();
           /* load Lua base libraries */
           lua_baselibopen(L);
           /* register our function */
           lua_register(L, "average", average);
           /* run the script */
           lua_dofile(L, "avg.lua");
           /* cleanup Lua */
           lua_close(L);
           return 0;
    }
    下面是一个简单的Lua脚本:
    -- simple test
    代码print "Hello, World!"
    确认它能运行。
    编译:
    使用你喜欢的编译器编译上面保存的C/C++文件,下面以Linux为例:
    命令行键入:
    代码:g++ luatest.cpp -llua -llualib -o luatest
    如果没有错误的话,运行程序:
    代码:./luatest
    程序应该打印出:Hello, World!
    如果你不是Linux操作系统,使用的是Vc++编译器,你需要:
    1. 创建一个新的win32控制台应用工程。
    2. 将文件luatest.cpp添加到你的工程中。
    3. 到Project, Settings点击Link页。
    4. 添加lua+lib.lib到Object/library modules列表中。
    5. 按F7编译程序。
    运行程序以前,你需要确保lua+lib.dll文件放在windows可以找到的地方,将这个文件从C:\Program Files\Lua-5.0拷贝到Visual C++ project目录,如果编译没有错误的话,现在可以Ctrl+F5运行程序了。

  • 相关阅读:
    并不对劲的CF1236D&E:Alice&Doll&UnfairGame
    并不对劲的CF1194E:Count The Rectangles
    并不对劲的CF1239B&C&D Programming Task in the Train to Catowice City
    并不对劲的初赛蒙猜凑思路
    并不对劲的CF1237D&E:Balanced Playlist and Binary Search Trees
    并不对劲的???
    并不对劲的P5589
    (简单) POJ 1511 Invitation Cards,SPFA。
    (简单) POJ 3159 Candies,Dijkstra+差分约束。
    (简单) POJ 2502 Subway,Dijkstra。
  • 原文地址:https://www.cnblogs.com/strinkbug/p/1752692.html
Copyright © 2020-2023  润新知