luacurl源码阅读4 - ALL_CURL_OPT宏
luacurl.c文件定义处的ALL_CURL_OPT展开
/* wrap curl option with simple option type */ #define C_OPT(n, t) /* wrap curl option with string list type */ #define C_OPT_SL(n) static const char* KEY_##n = #n; /* wrap the other curl options not included above */ #define C_OPT_SPECIAL(n) //因为C_OPT和C_OPT_SPECIAL都是空的,所以下面忽略了 /* describes all currently supported curl options available to curl 7.15.2 */ #define ALL_CURL_OPT \ C_OPT_SL(HTTPHEADER) \ /* 相当于: static const char* KEY_HTTPHEADER = "HTTPHEADER"; */ C_OPT_SL(HTTPPOST) \ /* 相当于: static const char* KEY_HTTPPOST = "HTTPPOST"; */ C_OPT_SL(QUOTE) \ /* 相当于: static const char* KEY_QUOTE = "QUOTE"; */ C_OPT_SL(POSTQUOTE) \ /* 相当于: static const char* KEY_POSTQUOTE = "POSTQUOTE"; */ C_OPT_SL(TELNETOPTIONS) \ /* 相当于: static const char* KEY_TELNETOPTIONS = "TELNETOPTIONS"; */ C_OPT_SL(PREQUOTE) \ /* 相当于: static const char* KEY_PREQUOTE = "PREQUOTE"; */ C_OPT_SL(HTTP200ALIASES) \ /* 相当于: static const char* KEY_HTTP200ALIASES = "HTTP200ALIASES"; */ C_OPT_SL(SOURCE_PREQUOTE) \ /* 相当于: static const char* KEY_SOURCE_PREQUOTE = "SOURCE_PREQUOTE"; */ C_OPT_SL(SOURCE_POSTQUOTE) \ /* 相当于: static const char* KEY_SOURCE_POSTQUOTE = "SOURCE_POSTQUOTE"; */ C_OPT_SL(SOURCE_QUOTE) \ /* 相当于: static const char* KEY_SOURCE_QUOTE = "SOURCE_QUOTE"; */ //...... ALL_CURL_OPT
lcurl_easy_setopt函数中的ALL_CURL_OPT展开
switch (curlOpt) { //CURLOPT_XxxDATA和CURLOPT_XxxFUNCTION部分的case //...... /* Handle all supported curl options differently according the specific option argument type */ #undef C_OPT #define C_OPT(n, t) \ case CURLOPT_##n: \ v=get_##t(L, 3); \ break; #undef C_OPT_SL #define C_OPT_SL(n) \ case CURLOPT_##n: \ { \ v=get_slist(L, 3, &KEY_##n); \ }break; /* Expands all the list of switch-case's here, 宏展开后, 就是剩余CURLOPT_Xxx的case */ ALL_CURL_OPT default: luaL_error(L, "Not supported curl option %d", curlOpt); }
相当于
switch (curlOpt) { case CURLOPT_URL: //对应 C_OPT(URL, string) v = get_string(L, 3); break; case CURLOPT_PORT: //对应 C_OPT(PORT, number) v = get_number(L, 3); break; case CURLOPT_HEADER: //对应 C_OPT(HEADER, boolean) v = get_boolean(L, 3); break; case CURLOPT_HTTPHEADER: //对应 C_OPT_SL(HTTPHEADER) v = get_slist(L, 3, &KEY_HTTPHEADER); break; case CURLOPT_HTTPPOST: //对应 C_OPT_SL(HTTPPOST) v = get_slist(L, 3, &KEY_HTTPPOST); break; //...... default: luaL_error(L, "Not supported curl option %d", curlOpt); }
下面的lua代码就会进入到ALL_CURL_OPT宏展开的case分支
local curl = require("libcurl") local c = curl.new() local headers = {} table.insert(headers, "Authorization: Bearer sk-xxxxxxxxxxxxx"); table.insert(headers, "Content-Type: application/json"); c:setopt(curl.OPT_HTTPHEADER, unpack(headers))
get_slist函数
/* after argument number n combine all arguments to the curl type curl_slist */ static union luaValueT get_slist(lua_State* L, int n, const char** key) { printf("get_slist begin: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, 1)) ); //4, userdata int i; union luaValueT v; struct curl_slist *slist=0; /* free the previous slist if any */ free_slist(L, key); printf("get_slist 111: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, 1)) ); //5, userdata /* check if all parameters are strings */ for (i=n; i<lua_gettop(L); i++) luaL_checkstring(L, i); for (i=n; i<lua_gettop(L); i++) { slist = curl_slist_append(slist, lua_tostring(L, i)); } /* set the new slist in registry */ lua_pushlightuserdata(L, (void*)key); lua_pushlightuserdata(L, (void *)slist); lua_rawset(L, LUA_REGISTRYINDEX); //等同于: 栈[LUA_REGISTRYINDEX][name] = slist, 执行完后栈顶弹出2个元素, name="userdata: "..keyAddr v.slist=slist; printf("get_slist end: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, 1)) ); //5, userdata return v; }
free_slist函数
/* remove and free old slist from registry if any associated with the given key */ static void free_slist(lua_State* L, const char** key) { printf("free_slist begin: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, 1)) ); //4, userdata struct curl_slist *slist; lua_pushlightuserdata(L, (void *)key); //变量地址压入栈顶 lua_rawget(L, LUA_REGISTRYINDEX); //栈[LUA_REGISTRYINDEX][k]的元素压入栈顶, k的值为: "userdata: "..keyAddr printf("free_slist 111: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, 1)) ); //5, userdata slist=(struct curl_slist *)lua_topointer(L, -1); //栈顶元素转换为指针 if (slist) { curl_slist_free_all(slist); } printf("free_slist end: %d, %s\n", lua_gettop(L), lua_typename(L, lua_type(L, 1)) ); //5, userdata }
lcurl_easy_close函数中的ALL_CURL_OPT展开
/* Finalizes CURL */ static int lcurl_easy_close(lua_State* L) { //...... #undef C_OPT #undef C_OPT_SL #undef C_OPT_SPECIAL #define C_OPT(n, t) #define C_OPT_SL(n) free_slist(L, &KEY_##n); #define C_OPT_SPECIAL(n) // 如果KEY_Xxx存放了对应的slist,则释放 ALL_CURL_OPT //...... }
相当于
//...... free_slist(L, &KEY_HTTPHEADER) free_slist(L, &KEY_HTTPPOST) free_slist(L, &KEY_QUOTE) free_slist(L, &KEY_POSTQUOTE) free_slist(L, &KEY_TELNETOPTIONS) free_slist(L, &KEY_PREQUOTE) free_slist(L, &KEY_HTTP200ALIASES) free_slist(L, &KEY_SOURCE_PREQUOTE) free_slist(L, &KEY_SOURCE_POSTQUOTE) free_slist(L, &KEY_SOURCE_QUOTE) //......

浙公网安备 33010602011771号