«Ошибка: попытка вызвать нулевое значение» при попытке вызвать скрипт lua - PullRequest
1 голос
/ 06 апреля 2011

Я пытаюсь вызвать функцию lua из C ++ и получаю сообщение об ошибке «Ошибка: попытка вызвать значение nil».

Функция lua создает объект C ++, а затем вызывает один изего методы, клеевой код был сгенерирован с помощью tolua ++.При вызове функции lua я передаю указатель lua_State, так как класс C ++ нуждается в указателе для своего конструктора, который ему вручает функция 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

Ответы [ 2 ]

1 голос
/ 06 апреля 2011

Оказывается, единственной проблемой было то, что в сценарии "lua2Function" было написано строчной буквой F. Код, который я вставил, на самом деле работает нормально. Как досадно!

Наверное, я узнал, что tolua ++ определенно заботится о передаче указателей lua_State в методы, по крайней мере.

0 голосов
/ 06 апреля 2011

Состояние Lua никогда явно не обрабатывается кодом Lua - оно неявно.Любая функция C ++, вызываемая Lua, не обязательно должна явно передавать переданное состояние - она ​​получает его как первый аргумент, который всегда передается Lua, независимо от других аргументов, потому что невозможно взаимодействовать с Lua каким-либо образом без lua_State*.Единственная причина сделать это, если у вас есть какое-то мета-состояние или если вы делаете что-то с кооперативными подпрограммами Lua.

Глобальная функция кажется достаточно простой и маловероятнойисточник ошибки.Вам нужно распечатать содержимое TestClass, чтобы убедиться, что оно имеет ожидаемое содержимое, а если нет, то это проблема, связанная с библиотекой привязки, и вам придется копаться в ее внутренностях, потому что этот код выглядит для меня как наиболее вероятная проблемаявляется то, что TestClass таблица не имеет то, что вы ожидаете, чтобы иметь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...