Skip to content

Instantly share code, notes, and snippets.

@leetking
Last active December 29, 2018 10:13
Show Gist options
  • Save leetking/98cdbc6e88742beb5abf1e28b44813cd to your computer and use it in GitHub Desktop.
Save leetking/98cdbc6e88742beb5abf1e28b44813cd to your computer and use it in GitHub Desktop.
用C编写lua模块

用C写lua模块

lua与c交互都是用过lua_State*类型的变量,并且是基于的。

Hello-Lua

文件: hello.c

#include <lua.h>
#include <lxlib.h>
#include <lualib.h>

/* 这里以lua5.1来示意 */
#define LUA_VERSION__   51
/*
 * 构造一个简单的函数
 */
static int hello(lua_State *L)
{
    char const *str;
    int age;
    str = luaL_checkstring(L, 1);   /* 传入的第一个参数是字符串(C风格的) */
    age = luaL_checkint(L, 2);      /* 传入的第二个参数是int型变量 */
    char tmp[512];
    snprintf(tmp, 512, "hello `%s`, your age is %d.", str, age);
    lua_pushstring(L, tmp);         /* 压入返回值 */
    return 1;                       /* 只有一个返回值 */
}
/* lua中函数名和c中函数映射 */
static const struct luaL_Reg funs[] = {
    {"say", hello},
    {NULL, NULL},
};
/*
 * lua中调用模块名为"hello"
 */
extern int luaopen_hello(lua_State *L)
{
    /* 在lua5.1之后注册函数变化了,LUA_VERSION__是我自己定义的宏:) */
#if (LUA_VERSION__ > 51)
    luaL_newlib(L, funs);
#else
    /* lua5.1 根据luaL_newlib函数,我们可以明白这里的"hello"参数并没有多大用 */
    luaL_register(L, "hello", funs);
#endif
    return 1;
}

这里给出一个简单的使用方法。

编译

$ # 由于是用c编写lua模块,所以并不需要链接lua的库,只需要其头文件,这里是lua5.1版本
$ gcc -o hello.so -shared -fPIC hello.c `pkg-config --cflags lua5.1`

使用

local hello = require("hello")
print(hello.say("leetking", 21))
-- hello `leetking`, your age is 21.

子模块

只需要把打开函数修改为luaopen_module_submodule,那么在lua中按照require("module.submodule")来使用。

复杂参数

  1. 返回表
lua_newtable(L);               /* index: -1 */
for (int i = 0; i <= nstr; ++i) {
   lua_pushnumber(L, i);       /* index: -2 */
   lua_pushstring(L, strs[i]); /* index: -3 */
   lua_settable(L, -3);        /* 弹出i和strs[i]放到表里 */
}
/* 返回的结果形如{1: "str1", 2: "str2"} */
  1. 参数压入弹出函数
  • lua_pushnil();
  • lua_pushnumber();
  • lua_pushstring();
  • lua_pushlstring();
  • lua_pushboolean();
  • luaL_checkint();
  • luaL_checklong();
  • luaL_checkstring();
  • luaL_checklstring();

补充

lua5.1中不支持形如"\xff\xa0"的十六进制字符串写法,但是是支持0xff十六进制常量的。

@xueliu
Copy link

xueliu commented Dec 1, 2018

应该是
#include <lauxlib.h>
而不是
#include <luaxlib.h>

@leetking
Copy link
Author

@xueliu 感谢,确实是 lauxlib.h 这里作笔记时,笔误了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment