Binding a LUA table function to a C++ variable using LUAPlus

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Binding a LUA table function to a C++ variable using LUAPlus

      Hi

      I'd like to start by saying that the book has been an amazing resource. I would also like to clarify that I've been using it more as a reference than following it step-by-step, which may be the reason I'm facing issues.

      I'm trying to add scripting to my AI, but I want to keep it simple for now. Just have the brain and movement LUA and handle everything else in C++. I set up a test project to tinker with LUAPlus until I have a firm grasp of it before adding it to my engine. The current issue I'm facing is binding a table member function to a C++ variable.
      In the code that I've added, Line 19 in the cpp works fine, but 27 causes a crash with the error message: "Assertion failed: 0, at ../luafunction.h line 41". When I remove lines 14-16 in test.lua, the error no longer happens.
      Based on this I assume the issue is that tableObj1.GetByName("functionName") returns a function with no reference to its parent table. I've read the source code for the TeapotWars and I can't see what I'm doing wrong.

      Here is my code
      main.cpp

      Source Code

      1. pLuaState = LuaPlus::LuaState::Create(true);
      2. pLuaState->DoFile("test.lua");
      3. LuaObject globals = pLuaState->GetGlobals();
      4. LuaObject metaTableObj = pLuaState->GetGlobals().Lookup("RandomMove");
      5. if (metaTableObj.IsNil())
      6. {
      7. metaTableObj = pLuaState->GetGlobals().CreateTable("RandomMove");
      8. }
      9. metaTableObj.SetObject("__index", metaTableObj);
      10. metaTableObj.RegisterObjectDirect("GetX", (TestLua*)0, &TestLua::GetX);
      11. metaTableObj.RegisterObjectDirect("SetX", (TestLua*)0, &TestLua::SetX);
      12. TestLua obj1(6);
      13. LuaObject table1Obj = pLuaState->GetGlobals().CreateTable("table1");
      14. table1Obj.SetLightUserData("__object", &obj1);
      15. table1Obj.SetObject("__index", metaTableObj);
      16. table1Obj.SetMetaTable(metaTableObj);
      17. pLuaState->DoString("table1:prints()");
      18. auto prints = table1Obj.GetByName("prints");
      19. if (!prints.IsFunction())
      20. cout << "nil function" << endl;
      21. else
      22. {
      23. LuaPlus::LuaFunction<void> func(prints);
      24. func();
      25. }
      Display All


      test.lua

      Source Code

      1. print("test.lua")
      2. RandomMove =
      3. {
      4. _thing = 1
      5. }
      6. function RandomMove:SetThing()
      7. print("I am "..tostring(self.__object))
      8. end
      9. function RandomMove:prints()
      10. print("in prints")
      11. print("__object is: " .. tostring(self.__object))
      12. print("_thing is: ".. tostring(self._thing))
      13. print(self:GetX())
      14. end
      Display All


    • Alright, so its a little hard to tell without seeing your console window, however I'll see if I can help. Depending on if you are using the master branch or the 'NextGen' branch of LuaPlus this may be different, but I am assuming it is the main branch (the one in GCC maybe?). The assert on line 41 is saying 'attempted to call a lua function with a single return value, but something failed', here is what is interesting, LuaPlus does retrieve the error string for you, but does nothing with it. What you need to do, is when this assert happens, inspect the 'errorString' variable. Let me know what that says.

      Second, this MAY not matter as the compiler seems to handle this case ok, but you should use LuaFunctionVoid, rather than LuaFunction<void>. Depending on the compiler this seems to at least pass the compilation (vc++ seems to work last time I checked). Some lua binding libs handle this properly and don't need a special 'Void' version of the function, which is due to the fact that if you have

      a) A template specialization for Type<void> which returns void
      b) Returning this specialization ie. return LPCD::Type<void>::Get(L, -1) basically translates to 'return;'

      Reference: stackoverflow.com/questions/33…how-to-handle-void-return
      PC - Custom Built
      CPU: 3rd Gen. Intel i7 3770 3.4Ghz
      GPU: ATI Radeon HD 7959 3GB
      RAM: 16GB

      Laptop - Alienware M17x
      CPU: 3rd Gen. Intel i7 - Ivy Bridge
      GPU: NVIDIA GeForce GTX 660M - 2GB GDDR5
      RAM: 8GB Dual Channel DDR3 @ 1600mhz
    • Thank you for the reply. I had asked the same question at StackOverflow, but due to the lack of LuaPlus activity I also posted here.
      The problem is that the function doesn't know who it belongs to, so you need to pass the object as the first argument (kind of like how the "this" pointer is a hidden argument in C++).
      So this

      Source Code

      1. func()

      should be this

      Source Code

      1. func(table1Obj)


      Here is the StackOverflow question for reference
    • Ah of course, sorry I missed that.
      PC - Custom Built
      CPU: 3rd Gen. Intel i7 3770 3.4Ghz
      GPU: ATI Radeon HD 7959 3GB
      RAM: 16GB

      Laptop - Alienware M17x
      CPU: 3rd Gen. Intel i7 - Ivy Bridge
      GPU: NVIDIA GeForce GTX 660M - 2GB GDDR5
      RAM: 8GB Dual Channel DDR3 @ 1600mhz