ngin Finding Everything About Nginx Here

用c编写lua扩展

发表于 2015-06-28 阅读数 2595

用c编写lua扩展

lua本身以小巧精致著称,但同是又提供良好机制以支持开发者编写其扩展模块。本文将介绍用c编写lua扩展,让您根据业务需要轻松实现自己的扩展模块。本文基于lua 5.3,推荐您先阅读编写lua扩展模块


1、第一种方式,函数形式

#include <lua.h>

#include <lualib.h>

#include <lauxlib.h>


/* gcc test.c -Wall -shared -o test.so [32位] */

/* gcc test.c -Wall -shared -o test.so -fPIC [64位] */

static int luaM_test(lua_State *L)

{

    printf("test");


    return 0;

}

static const luaL_Reg test_funcs[] = {

    {"test", luaM_test},

    {NULL, NULL}

};

int luaopen_test(lua_State *L)

{

    printf("open test module\n");

    return 0;

}

luaopen_xxx会在require('xxx')时自动调用,这基于dlopen的机制。

然后将生成的test.so放到指定的模块路径下。还记得前文的路径查找吗?

no field package.preload['m']

no file '/usr/local/share/lua/5.3/m.lua'

no file '/usr/local/share/lua/5.3/m/init.lua'

no file '/usr/local/lib/lua/5.3/m.lua'

no file '/usr/local/lib/lua/5.3/m/init.lua'

no file './m.lua'

no file './m/init.lua'

no file '/usr/local/lib/lua/5.3/m.so'

no file '/usr/local/lib/lua/5.3/loadall.so'

no file './m.so'


这个规则同样适合c的扩展。但是指定路径的变量换成 package.cpath


2、第二种方式,对象方式

#include <lua.h>

#include <lualib.h>

#include <lauxlib.h>


/* gcc test.c -Wall -shared -o test.so [32位] */

/* gcc test.c -Wall -shared -o test.so -fPIC [64位] */

static int luaM_test(lua_State *L)

{

    printf("test");

    return 0;

}


static const luaL_Reg test_funcs[] = {

    {"test", luaM_test},

    {NULL, NULL}

};

int luaopen_test(lua_State *L)

{

    luaL_newlib(L, test_funcs);

    return 1;

}


3、更多资源:

以下来自 https://code.google.com/p/zester/wiki/Lua_C

#include <stdio.h>

#include "lua.h"

#include "lualib.h"

#include "lauxlib.h"


/* gcc -o luadd luadd.c -I/usr/local/include -L/usr/local/lib -llua -lm -ldl */


/* 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_tointeger(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 */

        luaL_openlibs(L);


        /* load the script */

        luaL_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);


        /* pause */

        printf( "Press enter to exit..." );


        getchar();


        return 0;

}

add.lua


-- add two numbers

function add ( x, y )

        return x + y

end

How to load and call a lua function from c

//last.cc

# extern "C" {

# #include "lua.h"

# #include "lualib.h"

# #include "lauxlib.h"

# }  


int main()

{

    double z;

    lua_State *L = lua_open();

    luaL_openlibs(L);

    if (luaL_loadfile(L, "last.lua") || lua_pcall(L, 0, 0, 0)) {

        printf("error: %s", lua_tostring(L, -1));

        return -1;

    }


    lua_getglobal(L, "f");

    if(!lua_isfunction(L,-1))

    {

        lua_pop(L,1);

        return -1;

    }

    lua_pushnumber(L, 21);   /* push 1st argument */

    lua_pushnumber(L, 31);   /* push 2nd argument */


    /* do the call (2 arguments, 1 result) */

    if (lua_pcall(L, 2, 1, 0) != 0) {

        printf("error running function `f': %s\n",lua_tostring(L, -1));

        return -1;

    }


    /* retrieve result */

    if (!lua_isnumber(L, -1)) {

        printf("function `f' must return a number\n");

        return -1;

    }

    z = lua_tonumber(L, -1);

    printf("Result: %f\n",z);

    lua_pop(L, 1);

    lua_close(L);


    return 0;

}

-- last.lua

function f (x, y)

    return (x^2 * math.sin(y))/(1 - x)

end

How to execute a Lua Script from C.

luatest.c


#include "lua.h"

#include "lualib.h"

#include "lauxlib.h"


/* gcc -o luatest luatest.c -I/usr/local/include -L/usr/local/lib -llua -lm -ldl */


int main()

{

    int s=0;

    lua_State *L = lua_open();


    // load the libs

    luaL_openlibs(L);


    //run a Lua scrip here

    luaL_dofile(L,"foo.lua");


    printf("\nAllright we are back in C.\n");


    lua_close(L);


    return 0;

}

foo.lua


io.write("Please enter your name: ")

name = io.read() -- read input from user

print ("Hi " .. name .. ", did you know we are in lua right now?")

How to get a Variable value from Lua to C.

test.c


#include <stdio.h>

#include <lua.h>

#include <lualib.h>

#include <lauxlib.h>

#include <string.h>


/* gcc -o test test.c -I/usr/local/include -L/usr/local/lib -llua -lm -ldl */


int main()

{

        lua_State *L = lua_open(); 

        

        if(luaL_loadfile(L,"settings.lua") || lua_pcall(L,0,0,0))

                printf("Error failed to load %s",lua_tostring(L,-1));

        else

        {

                        

            lua_getglobal(L,"screenWidth");

            const int screenWidth = lua_tonumber(L,-1);

            printf("Screen Width = %d \n", screenWidth);

            

            lua_getglobal(L,"appName");

            const char *appName = luaL_checkstring(L, -1);      

            printf("Screen Name = %s \n", appName);


        }

        

        lua_close(L);


        /* If we got this far, everything worked */

        printf("Success!\n");


        return 0;

}

settings.lua


appName = "Firefox"

screenWidth = 400

How to write a lua binding in C.

zstring.c


#include "lua.h"

#include "lualib.h"

#include "lauxlib.h"

#include <string.h>


/* gcc zstring.c -Wall -shared -o zstring.so */



static int zst_strlen(lua_State *L)

{

    size_t len;

    len = strlen(lua_tostring(L, 1));

    lua_pushnumber(L, len);

    return 1;

}


int luaopen_zstring(lua_State *L) 

{

    lua_register(L,"zst_strlen", zst_strlen);

    return 0;

}

require "zstring"

print(zst_strlen("Hello, World"))

Another Binding Example

#include "lua.h"

#include "lualib.h"

#include "lauxlib.h"

#include <unistd.h>

#include <sys/stat.h>

#include <stdlib.h>


/* gcc general.c -Wall -shared -o general.so */


/* system */

static int zst_exec(lua_State *L)

{

        int status;

    status = system(lua_tostring(L, 1));

    lua_pushnumber(L, status);

    return 1;

}


/* mkdir */

static int zst_mkdir(lua_State *L)

{

        int status;

        mode_t mode = lua_tonumber(L, 2);

        status = mkdir(lua_tostring(L, 1), mode);

        lua_pushnumber(L, status);

        return 1;

}


/* symlink */ 

static int zst_symlink(lua_State *L)

{

        int status;

        const char *old = lua_tostring(L, 1);

        const char *new = lua_tostring(L, 2);

        status = symlink(old, new);

        lua_pushnumber(L, status);

        return 1;

}


/* rmdir */

static int zst_rmdir(lua_State *L)

{

        int status;

        status = rmdir(lua_tostring(L, 1));

        lua_pushnumber(L, status);

        return 1;

}


/* rename */

static int zst_rename(lua_State *L)

{

    int status;

    const char *old = lua_tostring(L, 1);

    const char *new = lua_tostring(L, 2);

    status = rename(old, new);

    lua_pushnumber(L, status);

    return 1;   

}


/* remove */

static int zst_remove(lua_State *L)

{

        int status;

        const char *filename = lua_tostring(L, 1);

        status = remove(filename);

        lua_pushnumber(L, status);

        return 1;

}


/* chown */

static int zst_chown(lua_State *L)

{

    int status;

    const char *filename = lua_tostring(L, 1);

    uid_t owner = lua_tonumber(L, 2);

    gid_t group = lua_tonumber(L, 3);

    status = chown(filename, owner, group);

    lua_pushnumber(L, status);

    return 1;   

}


/* chmod */

static int zst_chmod(lua_State *L)

{

    int status;

    const char *filename = lua_tostring(L, 1);

    mode_t mode = lua_tonumber(L, 2);

    status = chmod(filename, mode);

    lua_pushnumber(L, status);

    return 1;


}


/* get_current_dir_name */

static int zst_getcwd(lua_State *L)

{

    char *dir;

    dir = get_current_dir_name();

    lua_pushstring(L, dir);

    return 1;

}


int luaopen_general(lua_State *L) 

{

    lua_register(L,"zst_exec", zst_exec);

    lua_register(L,"zst_mkdir", zst_mkdir);

    lua_register(L,"zst_symlink", zst_symlink);

    lua_register(L,"zst_rmdir", zst_rmdir);

    lua_register(L,"zst_rename", zst_rename);

    lua_register(L,"zst_remove", zst_remove);

    lua_register(L,"zst_chown", zst_chown);

    lua_register(L,"zst_chmod", zst_chmod);

    lua_register(L,"zst_getcwd", zst_getcwd);


    return 0;

}