luacurl源码阅读2 - binding函数(static函数)

 注册在curl表下,可以看作curl类的static函数

static const struct luaL_reg luacurl_funcs[] =
{
    {"new", lcurl_easy_init},
    {"escape", lcurl_escape},
    {"unescape", lcurl_unescape},
    {0, 0}
};

LUACURL_API int luaopen_luacurl (lua_State *L) 
{  
    //......

    luaL_openlib (L, LUACURL_LIBNAME, luacurl_funcs, 0); //新建一个表 curl, 压入栈顶, 将表保存在: 栈[LUA_GLOBALSINDEX]["curl"] = curl, 函数注册在curl下

    //......

    return 1; //栈顶弹出1个元素, 作为lua层拿到的返回值
}

 

lcurl_easy_init函数

/* Initializes CURL connection */
static int lcurl_easy_init(lua_State* L)
{
    printf("lcurl_easy_init begin: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, -1)) ); //

    curlT* c = (curlT*)lua_newuserdata(L, sizeof(curlT)); //创建一个userdata, 并压入栈顶
    printf("lcurl_easy_init 111: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, -1)) ); //
    c->L=L; //关联lua虚拟机指针
    //设置初始值
    c->freaderRef=c->fwriterRef=c->fprogressRef=c->fheaderRef=c->fioctlRef=LUA_REFNIL;
    c->rud.nval=c->wud.nval=c->pud.nval=c->hud.nval=c->iud.nval=0;
    c->rudtype=c->wudtype=c->pudtype=c->hudtype=c->iudtype=LUA_TNIL;

    /* open curl handle */
    c->curl = curl_easy_init();
    /* set metatable to curlT object */
    luaL_getmetatable(L, CURLHANDLE); //获取栈[LUA_REGISTRYINDEX][CURLHANDLE]处的table, 并压入栈顶, 如果没有则压入nil
    printf("lcurl_easy_init 222: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, -1))); //
    lua_setmetatable(L, -2); //相当于setmetatable(userdata, curlT),执行完后栈顶弹出1个元素

    printf("lcurl_easy_init end: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, -1))); //

    return 1; //栈顶弹出1个元素, 作为lua层拿到的返回值
}

上面的代码相当于lua代码:

local curlContext = {}
setmetatable(curlContext, curlT)
return curlContext;

 

下面的lua代码,就会调用c层的lcurl_easy_init

local curl = require("luacurl")
local obj = curl.new()

 

lcurl_escape函数

/* Escapes URL strings */
static int lcurl_escape(lua_State* L)
{
    printf("lcurl_escape begin: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, -1)) ); // 1, string

    if (!lua_isnil(L, 1)) //栈底的值的类型是否为nil, 用栈底是因为可以给escape传多个参数, 但只会取第1个参数
    {
        const char* s=luaL_checkstring(L, 1);
        printf("lcurl_escape 111: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, -1)) ); // 1, string
        lua_pushstring(L, curl_escape(s, (int)lua_strlen(L, 1)));
        printf("lcurl_escape end: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, -1)) ); // 2, string
        return 1; //栈顶弹出1个元素, 作为lua层拿到的返回值
    } else
    {
        luaL_argerror(L, 1, "string parameter expected");
    }

    printf("lcurl_escape end: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, -1)));
    return 0;
}

下面的lua代码,就会调用c层的lcurl_escape

local curl = require("libcurl")
local str = curl.escape("a b", "cd e") --第2个参数会被忽略
print(str) --a%20b

 

local str = curl.escape(function() end) --luaL_checkstring检查不通过,会报异常

 

lcurl_unescape函数

/* Unescapes URL encoding in strings */
static int lcurl_unescape(lua_State* L)
{
    printf("lcurl_unescape begin: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, -1))); // 1, string

    if (!lua_isnil(L, 1))
    {
        const char* s=luaL_checkstring(L, 1);
        printf("lcurl_unescape 111: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, -1))); // 1, string
        lua_pushstring(L, curl_unescape(s, (int)lua_strlen(L, 1)));
        printf("lcurl_unescape end: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, -1))); // 2, string
        return 1; //栈顶弹出1个元素, 作为lua层拿到的返回值
    } else
    {
        luaL_argerror(L, 1, "string parameter expected");
    }
    return 0;
}

下面的lua代码,就会调用c层的unescape

local str2 = curl.unescape("a%20b")
print(str2) --a b

 

posted @ 2025-07-05 15:52  yanghui01  阅读(6)  评论(0)    收藏  举报