Question

I have a C++ class that I want to give access to in the lua script through a global variable, however when I try to use it I get the following error:

terminate called after throwing an instance of 'luabind::error'
  what():  lua runtime error
baz.lua:3: attempt to index global 'foo' (a nil value)Aborted (core dumped)

My Lua script (baz.lua) looks like this:

-- baz.lua
frames = 0
bar = foo:createBar()

function baz()
  frames = frames + 1

  bar:setText("frame: " .. frames)
end

And I'm made a simple and short (as well as I could) main.cpp that recreates this problem:

#include <memory>
#include <iostream>

extern "C" {
  #include "lua.h"
  #include "lualib.h"
  #include "lauxlib.h"
}

#include <boost/ref.hpp>
#include <luabind/luabind.hpp>

class bar
{
public:
  static void init(lua_State *L)
  {
    using luabind::module;
    using luabind::class_;

    module(L)
    [
      class_<bar>("bar")
        .def("setText", &bar::setText)
    ];
  }

  void setText(const std::string &text)
  {
    std::cout << text << std::endl;
  }
};

class foo
{
public:
  foo() :
    L(luaL_newstate())
  {
    int ret = luaL_dofile(L, "baz.lua");
    if (ret != 0) {
      std::cout << lua_tostring(L, -1);
    }

    luabind::open(L);

    using luabind::module;
    using luabind::class_;

    module(L)
    [
      class_<foo>("bar")
        .def("createBar", &foo::createBar)
    ];

    bar::init(L);
    luabind::globals(L)["foo"] = boost::ref(*this);
  }

  boost::reference_wrapper<bar> createBar()
  {
    auto b = std::make_shared<bar>();
    bars_.push_back(b);

    return boost::ref(*b.get());
  }

  void baz()
  {
    luabind::call_function<void>(L, "baz");
  }

private:
  lua_State *L;
  std::vector<std::shared_ptr<bar>> bars_;
};

int main()
{
  foo f;

  while (true) {
    f.baz();
  }
}

This is compiled with:

g++ -std=c++11 -llua -lluabind main.cpp

I've discovered that if I put the bar = foo:createBar() into the baz() function then it doesn't error, so I assume I'm not initialising the globals in the global namespace correctly? Am I missing a luabind function that I need to call before I am able to do this? Or is this just not possible at all...

Thanks!

Was it helpful?

Solution

You're running baz.lua before you register any globals. Put the dofile command after registering your bindings.

The sequence is as follows:

  • You invoke foo's constructor in C++, which
  • creates a Lua state
  • runs lua.baz
  • registers your bindings
  • then in c++ you call f.baz.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top