簡體   English   中英

嘗試調用lua腳本時出現“錯誤:嘗試調用nil值”

[英]“Error: attempt to call a nil value” when trying to call lua script

我正在嘗試從C ++調用lua函數,並且不斷收到錯誤消息“錯誤:嘗試調用nil值”。

lua函數創建一個C ++對象,然后調用其方法之一,該膠合代碼已使用tolua ++生成。 當調用lua函數時,我傳入了lua_State指針,因為C ++類的構造函數需要一個lua_State指針,而lua函數會將其傳遞給它。

但是據我所知,它永遠也不會運行腳本。 至少該錯誤沒有引用腳本中的任何行號。

這是調用該函數的C ++代碼:

int main()
{

lua_State *lState;

lState = luaL_newstate(); //new lua state
tolua_TestClass_open (lState); //open libs for TestClass

int iStatus = luaL_loadfile( lState, "lua1.lua" ); //load script
if (iStatus)
{
    std::cout << "Error: " << lua_tostring( lState, -1 );
    return 1;
}

iStatus = lua_pcall( lState, 0, 0, 0); //initialise the lua script
if( iStatus )
{
    std::cout << "Error: " << lua_tostring( lState, -1 );
    return 1;
}

lua_getglobal( lState, "lua1Function" ); //starting the function call
lua_pushlightuserdata (lState, lState); //lState is also being passed in as a parameter

iStatus = lua_pcall( lState, 1, 0, 0 ); //calling on this lua state with 1 argument expecting 0 outputs
if( iStatus ) //error checking
{
    std::cout << "Error: " << lua_tostring( lState, -1 );
    return 1;
}

return 1;
}

這是lua腳本:

function lua1Function(lstate)
tclass = TestClass:new();
tclass:method1();
tclass:method3();
end

我敢肯定,這不像忘記做那么簡單:

tclass = TestClass:new(lstate);

正如膠水代碼似乎表明我不需要這樣做,在這里:

/* method: new of class  TestClass */
#ifndef TOLUA_DISABLE_tolua_TestClass_TestClass_new00
static int tolua_TestClass_TestClass_new00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
 tolua_Error tolua_err;
 if (
     !tolua_isusertable(tolua_S,1,"TestClass",0,&tolua_err) ||
     !tolua_isnoobj(tolua_S,2,&tolua_err)
 )
  goto tolua_lerror;
 else
#endif
 {
  lua_State* tolua_var_1 =  tolua_S; //seems to know I want the lua_State by default,
//usually it will pop a usertype or luanumber or whatever off the stack,
//depending on the parameter
  {
   TestClass* tolua_ret = (TestClass*)  Mtolua_new((TestClass)(tolua_var_1));
    tolua_pushusertype(tolua_S,(void*)tolua_ret,"TestClass");
  }
 }
 return 1;
#ifndef TOLUA_RELEASE
 tolua_lerror:
 tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
 return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE

THAT產生的錯誤消息似乎證實了我的理論:“函數'new'中的錯誤。參數2是'userdata';應該是'[no object]'”。 即,沒想到/不需要我傳遞那個lua_State指針

我很茫然,我很難找到解決lua問題的解決方案,因為在涉及tolua ++方面,教程/文檔似乎很薄,但是現在更改綁定庫為時已晚。

任何幫助將不勝感激,我希望我已提供足夠的診斷問題的方法。

編輯:這是我的TestClass.cpp代碼(您可能會忽略method1、2和3,因為似乎由於此錯誤而未調用它們):

#include "TestClass.h"
#include <iostream>

TestClass::TestClass(lua_State *L)
{
    num = NULL;
    lState = L;
}

int TestClass::method1()
{
    int iStatus = luaL_loadfile( lState, "lua2.lua" );
    if (iStatus)
    {
        std::cout << "Error: " << lua_tostring( lState, -1 );
        return 1;
    }

    iStatus = lua_pcall( lState, 0, 0, 0); //this might be to initialise the lua script
    if( iStatus )
    {
        std::cout << "Error: " << lua_tostring( lState, -1 );
        return 1;
    }

    ///////////call lua function, passing on self pointer onto the stack////////////////

    lua_getglobal( lState, "lua2Function" );
    tolua_pushusertype(lState, this, "TestClass");

    iStatus = lua_pcall( lState, 1, 1, 0 );
    if( iStatus ) //error checking
    {
        std::cout << "Error: " << lua_tostring( lState, -1 );
        return 1;
    }

    ///////////lua function returns an int, return it////////////
    num = lua_tointeger( lState, -1 );

    return 0;
}

int TestClass::method2(int i)
{
    i += 2;
    return i;
}

void TestClass::method3()
{
    std::cout << (char)num << std::endl;
}

/*
** Lua binding: TestClass
** Generated automatically by tolua++-1.0.92 on 04/05/11 17:59:24.
*/

#ifndef __cplusplus
#include "stdlib.h"
#endif
#include "string.h"

#include "tolua++.h"


/* function to release collected object via destructor */
#ifdef __cplusplus

static int tolua_collect_TestClass (lua_State* tolua_S)
{
 TestClass* self = (TestClass*) tolua_tousertype(tolua_S,1,0);
    Mtolua_delete(self);
    return 0;
}
#endif


/* function to register type */
static void tolua_reg_types (lua_State* tolua_S)
{
 tolua_usertype(tolua_S,"TestClass");
}

/* method: new of class  TestClass */
#ifndef TOLUA_DISABLE_tolua_TestClass_TestClass_new00
static int tolua_TestClass_TestClass_new00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
 tolua_Error tolua_err;
 if (
     !tolua_isusertable(tolua_S,1,"TestClass",0,&tolua_err) ||
     !tolua_isnoobj(tolua_S,2,&tolua_err)
 )
  goto tolua_lerror;
 else
#endif
 {
  lua_State* tolua_var_1 =  tolua_S;
  {
   TestClass* tolua_ret = (TestClass*)  Mtolua_new((TestClass)(tolua_var_1));
    tolua_pushusertype(tolua_S,(void*)tolua_ret,"TestClass");
  }
 }
 return 1;
#ifndef TOLUA_RELEASE
 tolua_lerror:
 tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
 return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE

/* method: new_local of class  TestClass */
#ifndef TOLUA_DISABLE_tolua_TestClass_TestClass_new00_local
static int tolua_TestClass_TestClass_new00_local(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
 tolua_Error tolua_err;
 if (
     !tolua_isusertable(tolua_S,1,"TestClass",0,&tolua_err) ||
     !tolua_isnoobj(tolua_S,2,&tolua_err)
 )
  goto tolua_lerror;
 else
#endif
 {
  lua_State* tolua_var_1 =  tolua_S;
  {
   TestClass* tolua_ret = (TestClass*)  Mtolua_new((TestClass)(tolua_var_1));
    tolua_pushusertype(tolua_S,(void*)tolua_ret,"TestClass");
    tolua_register_gc(tolua_S,lua_gettop(tolua_S));
  }
 }
 return 1;
#ifndef TOLUA_RELEASE
 tolua_lerror:
 tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
 return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE

/* method: method1 of class  TestClass */
#ifndef TOLUA_DISABLE_tolua_TestClass_TestClass_method100
static int tolua_TestClass_TestClass_method100(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
 tolua_Error tolua_err;
 if (
     !tolua_isusertype(tolua_S,1,"TestClass",0,&tolua_err) ||
     !tolua_isnoobj(tolua_S,2,&tolua_err)
 )
  goto tolua_lerror;
 else
#endif
 {
  TestClass* self = (TestClass*)  tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
  if (!self) tolua_error(tolua_S,"invalid 'self' in function 'method1'", NULL);
#endif
  {
   int tolua_ret = (int)  self->method1();
   tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
  }
 }
 return 1;
#ifndef TOLUA_RELEASE
 tolua_lerror:
 tolua_error(tolua_S,"#ferror in function 'method1'.",&tolua_err);
 return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE

/* method: method2 of class  TestClass */
#ifndef TOLUA_DISABLE_tolua_TestClass_TestClass_method200
static int tolua_TestClass_TestClass_method200(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
 tolua_Error tolua_err;
 if (
     !tolua_isusertype(tolua_S,1,"TestClass",0,&tolua_err) ||
     !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
     !tolua_isnoobj(tolua_S,3,&tolua_err)
 )
  goto tolua_lerror;
 else
#endif
 {
  TestClass* self = (TestClass*)  tolua_tousertype(tolua_S,1,0);
  int tolua_var_2 = ((int)  tolua_tonumber(tolua_S,2,0));
#ifndef TOLUA_RELEASE
  if (!self) tolua_error(tolua_S,"invalid 'self' in function 'method2'", NULL);
#endif
  {
   int tolua_ret = (int)  self->method2(tolua_var_2);
   tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
  }
 }
 return 1;
#ifndef TOLUA_RELEASE
 tolua_lerror:
 tolua_error(tolua_S,"#ferror in function 'method2'.",&tolua_err);
 return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE

/* method: method3 of class  TestClass */
#ifndef TOLUA_DISABLE_tolua_TestClass_TestClass_method300
static int tolua_TestClass_TestClass_method300(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
 tolua_Error tolua_err;
 if (
   !tolua_isusertype(tolua_S,1,"TestClass",0,&tolua_err) ||
   !tolua_isnoobj(tolua_S,2,&tolua_err)
     )
  goto tolua_lerror;
 else
#endif
 {
  TestClass* self = (TestClass*)  tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
  if (!self) tolua_error(tolua_S,"invalid 'self' in function 'method3'", NULL);
#endif
  {
   self->method3();
  }
 }
 return 0;
#ifndef TOLUA_RELEASE
 tolua_lerror:
 tolua_error(tolua_S,"#ferror in function 'method3'.",&tolua_err);
 return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE

/* Open function */
TOLUA_API int tolua_TestClass_open (lua_State* tolua_S)
{
 tolua_open(tolua_S);
 tolua_reg_types(tolua_S);
 tolua_module(tolua_S,NULL,0);
 tolua_beginmodule(tolua_S,NULL);
  #ifdef __cplusplus
  tolua_cclass(tolua_S,"TestClass","TestClass","",tolua_collect_TestClass);
  #else
  tolua_cclass(tolua_S,"TestClass","TestClass","",NULL);
  #endif
  tolua_beginmodule(tolua_S,"TestClass");
   tolua_function(tolua_S,"new",tolua_TestClass_TestClass_new00);
   tolua_function(tolua_S,"new_local",tolua_TestClass_TestClass_new00_local);
   tolua_function(tolua_S,".call",tolua_TestClass_TestClass_new00_local);
   tolua_function(tolua_S,"method1",tolua_TestClass_TestClass_method100);
   tolua_function(tolua_S,"method2",tolua_TestClass_TestClass_method200);
   tolua_function(tolua_S,"method3",tolua_TestClass_TestClass_method300);
  tolua_endmodule(tolua_S);
 tolua_endmodule(tolua_S);
 return 1;
}


#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
 TOLUA_API int luaopen_TestClass (lua_State* tolua_S) {
 return tolua_TestClass_open(tolua_S);
};
#endif

事實證明,唯一的問題是腳本中的lua2Function拼寫為小寫F。 我粘貼的代碼實際上可以正常工作。 多么徹底的尷尬!

我想我已經了解到,至少tolua ++確實確實負責將lua_State指針傳遞給方法。

Lua狀態永遠不會由Lua代碼顯式處理-它是隱式的。 Lua調用的任何C ++函數都不需要顯式傳遞狀態-它會獲得它作為第一個參數(無論其他參數如何)始終由Lua傳遞的第一個參數,因為沒有lua_State*就無法以任何方式與Lua進行交互lua_State* 這樣做的唯一原因是,如果您具有某種元狀態,或者正在使用Lua的合作式協作程序進行操作。

全局函數似乎足夠簡單,並且不太可能是錯誤的根源。 您需要打印TestClass的內容以驗證它是否具有預期的內容,否則,這是綁定庫特有的問題,您必須深入研究其內部,因為在我看來,該代碼看起來像是最可能出現的問題是TestClass表沒有您期望的表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM