LUA使用lua_pcall

时间:2017-08-09 16:50:38

标签: c linux lua

在lua_pcall之前设置不透明句柄时,我无法从C正确调用lua例程。 (注意:环境:Linux / OpenSuse42.2与LUA-5.3和GCC-5

我正在寻找的序列。

  • 从C开始(不是从LUA开始)。在C中创建不透明句柄(lua_newuserdata + luaL_setmetatable)
  • 设置例程以调用lua_getglobal(luaState,func);
  • 使用lua_pcall从C调用lua func(在我的脚本中调整Adjust_Volume_Speed)
  • 从LUA回拨C(在我的脚本AFB_sucess中)。注意:调用有效,LUA接收正确的参数
  • 回到C
  • 我可以得到我的lua例程参数但不是我的不透明句柄 失败(luaL_checktype(luaState,1,LUA_TUSERDATA);

您可以在此处查看我的LUA代码。从LUA调用AFB_sucess时,我无法检索我的userdata。

似乎:

  • 如果我在lua_getglobal(luaState,lua_func_name)之前推送user_data;然后不使用user_data。
  • 如果我在lua_getglobal之后推送用户数据,那么调用我的lua例程会失败并显示一条消息,告知我尝试调用user_data。

问题:当使用lua_pcall时,如何实现user_data,以便当LUA到达恰好在C中实现的回调时,我可以检索我的opaque句柄?

涉及的关键行是。

常规用于创建/检索不透明句柄

STATIC LuaAfbContextT *LuaCtxCheck (lua_State *luaState, int index) {
  LuaAfbContextT *afbContext;
  luaL_checktype(luaState, index, LUA_TUSERDATA);
  afbContext = (LuaAfbContextT *)luaL_checkudata(luaState, index, CTX_TOKEN);
  if (afbContext == NULL && afbContext->ctxMagic != CTX_MAGIC) {
      luaL_error(luaState, "Fail to retrieve user data context=%s", CTX_TOKEN);
      AFB_ERROR ("afbContextCheck error retrieving afbContext");
      return NULL;
  }
  return afbContext;
}

STATIC LuaAfbContextT *LuaCtxPush (lua_State *luaState, afb_req request, const char* info) {
  LuaAfbContextT *afbContext = (LuaAfbContextT *)lua_newuserdata(luaState, sizeof(LuaAfbContextT));
  if (!afbContext) {
      AFB_ERROR ("LuaCtxPush fail to allocate user data context");
      return NULL;
  }
  luaL_setmetatable(luaState, CTX_TOKEN);
  afbContext->ctxMagic=CTX_MAGIC;
  afbContext->info=strdup(info);
  afbContext->request= request;
  return afbContext;
}

从C创建LUA例程

 // Push AFB client context on the stack
        LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, func);
        if (!afbContext) goto OnErrorExit;

        // load function (should exist in CONTROL_PATH_LUA
        lua_getglobal(luaState, func);

        // push arguments on the stack
        if (json_object_get_type(args) != json_type_array) { 
            count= LuaPushArgument (args);
        } else {
            for (int idx=0; idx<json_object_array_length(args); idx++)  {
                count += LuaPushArgument (json_object_array_get_idx(args, idx));
                if (err) break;
            }
        } 

从C

调用LUA的例程
 static const luaL_Reg afbFunction[] = {
    {"notice" , LuaPrintNotice},
    {"warning", LuaPrintWarning},
    {"service", LuaAfbService},
    {"success", LuaAfbSuccess},
    {"fail"   , LuaAfbFail},
    {NULL, NULL}  /* sentinel */
};

// Create Binding Event at Init
PUBLIC int LuaLibInit () {
    int err, index;

    // search for default policy config file
    json_object *luaScriptPathJ = ScanForConfig(CONTROL_PATH_LUA , "onload", "lua");

    // open a new LUA interpretor
    luaState = luaL_newstate();
    if (!luaState)  {
        AFB_ERROR ("LUA_INIT: Fail to open lua interpretor");
        goto OnErrorExit;
    }

    // load auxiliary libraries
    luaL_openlibs(luaState);

    // redirect print to AFB_NOTICE    
    luaL_newlib(luaState, afbFunction);
    lua_setglobal(luaState, "AFB");


// Push AFB client context on the stack
        LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, func);
        if (!afbContext) goto OnErrorExit;

        // load function (should exist in CONTROL_PATH_LUA
        lua_getglobal(luaState, func);

        // push arguments on the stack
        if (json_object_get_type(args) != json_type_array) { 
            count= LuaPushArgument (args);
        } else {
            for (int idx=0; idx<json_object_array_length(args); idx++)  {
                count += LuaPushArgument (json_object_array_get_idx(args, idx));
                if (err) break;
            }
        } 

我的LUA脚本

-- Adjust Volume function of vehicle speed
function Adjust_Volume_Speed (speed_meters_second)

  AFB:notice("In Adjust_Volume_Speed")

   print (string.format("***** Adjust_Volume_Speed speed=%d count=%d", speed_meters_second, count));

   -- compute volume
   volume = speed_meters_second * 2
   count=count+1

  AFB:success (1234, volume, count, 5678) 
end

0 个答案:

没有答案