我的第一份供lua调用的c模块

#include <stdio.h>
#include <string>

#include <direct.h>
#include <windows.h>
#include <io.h>


extern "C" {
#include "D:\myPath\lua\5.3\include\lua.h"
#include "D:\myPath\lua\5.3\include\lauxlib.h"
#include "D:\myPath\lua\5.3\include\lualib.h"
}
#pragma comment(lib,"D:\\myPath\\lua\\5.3\\lib\\Lua53.lib")// 该模块和lua解释器都要使用动态链接
// 因为这是lua解释器也要用到的库,使用静态链接会报错 multiple Lua VMs detected

#define LUA_VERSION_NUM 503

// 使用static 防止名字污染
static int pusherror(lua_State *L, const char *info) // lua函数返回错误信息就是这么来的
{
    lua_pushnil(L);  // lua函数不是一出错就先返回  nil + info 的模式么?
    if (info == NULL)
        lua_pushstring(L, strerror(errno));
    else
        lua_pushfstring(L, "%s: %s", info, strerror(errno));
    lua_pushinteger(L, errno);
    return 3;
}
// 获取当前目录  因为会用到系统有关的目录api,所以cl编译时 运行时库选择 /MD 
static int get_dir (lua_State *L)
{
#ifdef NO_GETCWD
    lua_pushnil(L);
    lua_pushstring(L, "Function 'getcwd' not provided by system");
    return 2;
#else
    char *path = NULL;
    /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */
    size_t size = MAX_PATH; /* initial buffer size */
    int result;
    while (1)
    {
        path = (char *)realloc(path, size);
        if (!path) /* failed to allocate */
            return pusherror(L, "get_dir realloc() failed");
        if (_getcwd(path, size) != NULL)
        {
            /* success, push the path to the Lua stack */
            lua_pushstring(L, path);
            result = 1;
            break;
        }
        if (errno != ERANGE) { /* unexpected error */ //就是说expected的error 是ERANGE,
            result = pusherror(L, "get_dir getcwd() failed");
            break;
        }
        /* ERANGE = insufficient buffer capacity, double size and retry */
        size *= 2; 
    }
    free(path);
    return result;
#endif
}


static int l_split(lua_State*L){
 const char* s = luaL_checkstring(L,-2);
 const char* sep = luaL_checkstring(L,-1);
lua_newtable(L);
const char* e = s;
int i = 1;
  while((e= strchr(s,*sep))!=NULL){
    if(e-s==0){s=e+1;continue;} // 避免连续的*sep导致压入空串
    lua_pushlstring(L, s, e-s);
    lua_rawseti(L, -2, i++);
    s = e+1;
  }
  lua_pushstring(L, s);
  lua_rawseti(L, -2, i);

return 1;
}
static int gettable(lua_State *L)
{
    //lua_setfield lua_seti lua_settable   luaL_ref
    //lua_getfield lua_geti  lua_gettable   luaL_unref
    // luaL_unref是删除键值对 luaL_ref是自动生成唯一键
    lua_newtable(L);
    char value[32] = {0};
    char key[10] = {0};
    for(int i = 1; i <= 5; i++)
    {
        sprintf(value, "value: %d", i);
        lua_pushstring(L, value);
        lua_seti(L, -2, i);
    }

    for(int i = 6; i <= 10; ++i)
    {
        sprintf(key, "key %d", i);
        sprintf(value, "value %d", i);
        lua_pushstring(L, value);
        lua_setfield(L, -2, key);
    }

    for(int i = 11; i <= 15; ++i)
    {
        sprintf(key, "key %d", i);
        sprintf(value, "value %d", i);
        lua_pushstring(L, key);
        lua_pushstring(L, value);
        lua_settable(L, -3);
    }

    for(int i = 16; i <= 20; ++i)
    {
        sprintf(value, "value %d", i);
        lua_pushstring(L, value);
        luaL_ref(L, -2); // 这个 不用管key, luaL_ref是自动生成唯一的key
    }

    return 1;
}

// assumes the table is on the top of stack
static int printtable(lua_State *L)
{
    if(!lua_istable(L, -1))return 0;
    lua_len(L, -1);
    int nlen = lua_tointeger(L, -1);
    lua_pop(L, 1);// 注意 这里不是索引而是数量
    printf("table length:%d\n",nlen);
    for(int i = 1; i <= nlen; ++i)
    {
        lua_geti(L, -1, i);
        int t = lua_type(L, -1);
        switch(t)
        {
        case LUA_TSTRING:
            printf("%s\n", lua_tostring(L, -1));
            break;
        case LUA_TNUMBER:
        {
            if(lua_isinteger(L, -1))printf("%d\n", lua_tointeger(L, -1) );
            else printf("%f\n", lua_tonumber(L, -1));
        }
        break;
        default:printf("other type\n");
        }
        lua_pop(L, 1);
    }
    return 0;
}
static const struct luaL_Reg mylib[] =
{
    {"currentdir", get_dir},
    {"l_split", split},
    {"gettable", gettable},
    {"printtable",printtable},
    {NULL, NULL},
};

extern "C" __declspec(dllexport) int luaopen_mylib(lua_State *L)  // 必须是luaopen_+dll名的形式
//requre(name)=>会找name.dll 找到name.dll 中的 luaopen_name导出函数
{
    //luaL_register(L,"mylib",mylib); // 已弃用 会污染全局namespace

    //前面还可以加一些元表信息
    //设置 __gc  __index等写法
    luaL_newlib(L, mylib);
    // lua_setglobal(L, "mylib"); // 有了这一句就可以不用mylib =  require("mylib")了

    
    lua_pushliteral(L, "Copyright (C) 2003-2016 Kepler Project");
    lua_setfield(L, -2, "_COPYRIGHT");
    lua_pushliteral(L, "1.0 ");
    lua_setfield(L, -2, "_VERSION");
    return 1;
}

posted on 2016-11-20 17:03  ShawSpring  阅读(403)  评论(0)    收藏  举报

导航