luacurl源码阅读5 - Write回调和参数

writerCallback回调函数

static size_t writerCallback(void *ptr, size_t size, size_t nmemb, void *stream)
{
    curlT* c=(curlT*)stream; //stream参数是一个自定义数据, 通过setopt(CURLOPT_WRITEDATA)设置的
    lua_rawgeti(c->L, LUA_REGISTRYINDEX, c->fwriterRef); //栈[LUA_REGISTRYINDEX][xxxRefId]处的元素压入栈顶
    pushLuaValueT(c->L, c->wudtype, c->wud);
    //size:每数据块大小, nmemb:数据块个数
    lua_pushlstring(c->L, ptr, size * nmemb);
    lua_call(c->L, 2, 1);
    return (size_t)lua_tonumber(c->L, -1);
}

下面的lua代码,就会调用到c层的write回调函数

local curl = require("luacurl")

local respData = {}
local c = curl.new()
c:setopt(curl.OPT_URL, "http://httpbin.org/get")
c:setopt(curl.OPT_WRITEDATA, respData);
c:setopt(curl.OPT_WRITEFUNCTION, function(tab, str)
    if tab then --就是curl.OPT_WRITEDATA设置的对象
        table.insert(tab, str)
    end
    return #str
end);
local isOk, err = c:perform()
print("result", isOk, err, table.concat(respData))
c:close()

 

luaValueT

/* wrap values of arbitrary type */
union luaValueT
{
    struct curl_slist *slist;
    curl_read_callback rcb; //读回调函数指针
    curl_write_callback wcb; //写回调函数指针
    curl_progress_callback pcb;

#if CURL_NEWER(7,12,3)
    curl_ioctl_callback icb;
#endif

    long nval;
    char* sval;
    void* ptr;
};

 

curlT

/* CURL object wrapper type */
typedef struct
{
    CURL* curl; //curl对象
    lua_State* L; //lua虚拟机实例

    int fwriterRef; //存放Opt_WriteFunction的参数值
    int wudtype; //存放Opt_WriteData的参数类型
    union luaValueT wud; //存放Opt_WriteData的参数值

    int freaderRef;   int rudtype; union luaValueT rud;
    int fprogressRef; int pudtype; union luaValueT pud;
    int fheaderRef;   int hudtype; union luaValueT hud;
    int fioctlRef;    int iudtype; union luaValueT iud;
} curlT;

 

pushLuaValueT函数

/* push correctly luaValue to Lua stack */
static void pushLuaValueT(lua_State* L, int t, union luaValueT v)
{
    switch (t)
    {
        case LUA_TNIL: lua_pushnil(L); break;
        case LUA_TBOOLEAN: lua_pushboolean(L, v.nval); break;
        
        case LUA_TTABLE:
        case LUA_TFUNCTION: 
        case LUA_TTHREAD:
        case LUA_TUSERDATA: lua_rawgeti(L, LUA_REGISTRYINDEX, v.nval); break; //获取栈[LUA_REGISTRYINDEX][nval]处的元素并压入栈顶

        case LUA_TLIGHTUSERDATA: lua_pushlightuserdata(L, v.ptr); break; //栈顶压入指针变量存放的地址
        case LUA_TNUMBER: lua_pushnumber(L, v.nval); break;
        case LUA_TSTRING: lua_pushstring(L, v.sval); break;
        default: luaL_error(L, "invalid type %s\n", lua_typename(L, t));
    }
}

 

posted @ 2025-07-08 22:56  yanghui01  阅读(15)  评论(0)    收藏  举报