1

I'm trying to use a lua state within C++ and i need to pass it a str from C++, how ever when i try to call my function i wrote in lua, i get the error attempted to call nil value. It compiles straight into the lua environment, but when i type the expression in i get the error.

int main(int argc, char** argv){
  lua_State *L;
  L = luaL_newstate();

  string buff;
  const char* finalString;

  luaL_openlibs(L);
  luaL_dofile(L,argv[1]);

  getline(cin, buff);

  lua_getglobal(L, "InfixToPostfix");
  lua_pushstring (L, buff.c_str());

  lua_pcall(L, 1, 1, 0);

  finalString = lua_tostring(L, -1);

  printf("%s\n", finalString);

  lua_close(L);

}

from lua file:

function InfixToPostfix(str)

  print("before for loop")

  for i in string.gmatch(str, "%S+") do

it wont reach the print out before displaying error

2
  • I believe that error message, "attempted to call nil value" indicates that the global name does not exist as you have spelled it. Causes can be misspelling of the name or that the function declaration is in some scope other than global. See stackoverflow.com/questions/5559741/… and see also stackoverflow.com/questions/20380232/… as well as cc.byexamples.com/2008/06/21/… Commented Apr 23, 2017 at 1:50
  • 2
    Another possible reason is that the Lua file contains a syntax error. You should check the return value of luaL_dofile. Commented Apr 23, 2017 at 5:31

1 Answer 1

1

The following works for me just fine:

#include <iostream>
#include <string>
#include <lua.hpp>

int main(int argc, char** argv)
{
  lua_State *L;
  L = luaL_newstate();
  luaL_openlibs(L);

  if (argc != 2)
  {
    std::cerr << "Usage: " << argv[0] << " script.lua\n";
    return 1;
  }

  if ( luaL_dofile(L,argv[1]) != 0 )
  {
    std::cerr << lua_tostring(L, -1) << '\n';
    return 1;
  }

  std::string buff;
  std::getline(std::cin, buff);

  lua_getglobal(L, "InfixToPostfix");
  lua_pushstring (L, buff.c_str());

  if ( lua_pcall(L, 1, 1, 0) != 0)
  {
    std::cerr << lua_tostring(L, -1) << '\n';
    return 1;
  }

  if ( !lua_isstring(L, -1) )
  {
    std::cerr << "Error: Return value cannot be converted to string!\n";
    return 1;
  }

  const char * finalString = lua_tostring(L, -1);

  std::cout << finalString << '\n';

  lua_close(L);
}
function InfixToPostfix(str)
   print("before for loop")
   for i in string.gmatch(str, "%S+") do
      print(i)
   end
   return "Something"
end

For the C++ part you could also use the Selene library. This considerably reduces the amount of code needed, also no manual error checking is needed.

#include <iostream>
#include <string>
#include <selene.h>

int main(int argc, char** argv)
{
  sel::State L{true};

  if (argc != 2)
  {
    std::cerr << "Usage: " << argv[0] << " script.lua\n";
    return 1;
  }

  L.Load(argv[1]);

  std::string buff;
  std::getline(std::cin, buff);

  std::string finalString = L["InfixToPostfix"](buff);

  std::cout << finalString << '\n';
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.