satoren / kaguya

C++ binding to Lua
Boost Software License 1.0
345 stars 70 forks source link

Fail to execute simple Lua code with kaguya #57

Open CaillotKi opened 7 years ago

CaillotKi commented 7 years ago

Hi,

I've tried to compile and run some simple code using kaguya. I compiled the same code twice, first with my system binary and libraries (64 bits archlinux up to date) and then with a toolchain for 32 bits x86.

In both cases the compilation is successful, my problem is when I run the version compiled with the toolchain I get an error : "attempt to index a nil value" (which I don't get with the version compiled directly with my system).

I tried to replicate the code logic using only the lua C api and then compiled it again with my system binary and libraries then with the toolchain. In this case both binaries works as expected.

My system uses g++ 6.2.1 while the toolchain is using g++ 4.9.2 (both meeting kaguya requirements). I'm compiling with the std=c++11 option. My system uses lua 5.3.3 while the toolchain uses 5.2.2

Here is the code which get me the "attempt to index a nil value" error :

     #include "kaguya.hpp"

     kaguya::State luaState;

     auto scriptAdding2CppVariables = R"(
         return valA + valB
     )";

     // Loading script in Lua context.
     kaguya::LuaFunction luaFunc = luaState.loadstring(scriptAdding2CppVariables);

     auto a = 1;
     auto b = 2;

     // Exporting variables to Lua context (under the same they're used in the previous script).
     luaState["valA"] = a;
     luaState["valB"] = b;

     if (luaFunc() == a + b)
     {
         std::cout << "SUCCESS" << std::endl;
     }
     else
     {
         std::cout << "FAILED" << std::endl;
     }

And here is the equivalent with the C api which does not trigger any error.

     #ifdef __cplusplus
     #include <lua.hpp>
     #else
     # include <lua.h>
     # include <lualib.h>
     # include <lauxlib.h>
     #endif

     lua_State* state;

    auto scriptAdding2CppVariables = R"(
        function add (varA, varB)
            return varA + varB
        end
     )";

     /* initialize Lua */
     state = luaL_newstate();

     luaL_dostring(state, scriptAdding2CppVariables);
     lua_getglobal(state, "add");

     auto varA = 1;
     lua_pushnumber(state, varA);

     auto varB = 2;
     lua_pushnumber(state, varB);

     lua_call(state, 2, 1);

     /* call the add function */
     auto sum = (int)lua_tointeger(state, -1);
     lua_pop(state, 1);

     if(sum == varA + varB)
     {
           std::cout << "SUCCESS" << std::endl;
     }
     else
     {
          std::cout << "FAILED" << std::endl;
     }

     /* cleanup Lua */
     lua_close(state);

I've tried modifying scriptAdding2CppVariables (in the code version using kaguaya) to "return 1 + 2" and removed the statements to export the variables a and b into the lua context but I still get the same error. It leaves us with only 3 statements using lua. Commenting the call to luaFunc() does stop the error from occurring.

If anyone could tell me why I got this behavior I'd be grateful.

Thanks

satoren commented 7 years ago

Hi,

I don't get it error. but look like slightly different for C api and kaguya code.

Could you try it with code like the one below?

Match completely code with your C api code.

 kaguya::State luaState;
//load 'add' function to global
auto scriptAdding2CppVariables = R"(
  function add (varA, varB)
    return varA + varB
  end
)";
luaState.dostring(scriptAdding2CppVariables);

//get 'add' function from global
kaguya::LuaFunction luaFunc = luaState["add"];

auto a = 1;
auto b = 2;

if (luaFunc(a, b) == a + b)
{
  std::cout << "SUCCESS" << std::endl;
}
else
{
  std::cout << "FAILED" << std::endl;
}

If you do not want global to dirty.

kaguya::LuaFunction luaFunc = luaState.loadstring("local arg = {...}; return arg[1] + arg[2]");
auto a = 1;
auto b = 2;
assert (luaFunc(a, b) == a + b)

or

//load function returning function.
kaguya::LuaFunction getAddFunc = luaState.loadstring("return function(varA, varB) return varA + varB end");
// get 'add' function
kaguya::LuaFunction luaFunc = getAddFunc ();

// or omitted getAddFunc 
// kaguya::LuaFunction luaFunc = luaState.loadstring("return function(varA, varB) return varA + varB end")();

auto a = 1;
auto b = 2;
assert (luaFunc(a, b) == a + b)
CaillotKi commented 7 years ago

Hi,

Thanks for this quick answer. I tried your code sample, all three version of it (thanks for the alternatives by the way) and it's still the same. When using the tool chain -> "attempt to call a nil value", when using my system binary and libraries it's ok.

There must be some incompatibility with some of my toolchain's component I guess but which one ...

satoren commented 7 years ago

Hi

What is tool chain? Could it be that you used different lua_State* or _ENV .

CaillotKi commented 7 years ago

A toolchain is a set of utilities used for programming. It ensures among other things that your "tools" are compatible with each other. It allows you to make sure that no matter if the system you're developing on is up to date, no matter if it uses another version of a library than the target you're developing for, the output software will be able to run on the target you're developing for (the ld binary of the toolchain link against the version of the libraries which are available on the final target).

I'm sorry for this "confused" explanation, I'd suggest to check it out on the internet for a better one it is definitely worth to know what it is.

I doubt I'm using a different lua_State with the C api than with Kaguya since both are using the same headers and library (I obviously might have forgotten something so please, feel free to suggest any idea).

As for the _ENV I just quickly googled it but I have to admit I didn't get exactly what it was or what it was used for, let alone how I could be using a different one.

Thanks for your help