Possible problem with default_converter and tables

Catherine West <[email protected]>
Newsgroups gmane.comp.lang.lua.bind.user
Message-ID <[email protected]>
Using luabind 0.9 and gcc 4.2.1 on mac os x 10.6

I'm seeing what could (maybe?) be a problem with using a default_converter from lua tables.

I'm trying to define converters for various list-like types in my code, specifically std::vector.  When I pass a table to a c++ method with such a default_converter, lua crashes with free() on an invalid pointer as soon as the garbage collector is called.

I'm probably missing something simple here, but I can't figure it out.

Keep in mind that this is my first project with either lua or luabind, please be gentile if I'm missing something obvious :)

Thank you!

*** Lua Code ***

function first ()
  -- Doesn't crash
  -- t = TestClass(1, 3)

  -- Crashes
  t = TestClass({1, 2, 3})

  print(t:get(0))
  print(t:get(1))
  print(t:get(2))
end

function second ()
  print("About to call collectgarbage...")
  collectgarbage()
  print("Done calling collectgarbage!")
end

function test ()
  first()
  second()
end

*** C++ Code ***

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

#include <luabind/luabind.hpp>
#include <luabind/operator.hpp>

using namespace std;
using namespace luabind;

namespace luabind {
  template<typename ListType>
  struct default_converter<std::vector<ListType> > : native_converter_base<std::vector<ListType> > {
    static int compute_score(lua_State* L, int index) {
      return lua_type(L, index) == LUA_TTABLE ? 0 : -1;
    }

    std::vector<ListType> from(lua_State* L, int index) {
      std::vector<ListType> list;
      for (luabind::iterator i(luabind::object(luabind::from_stack(L, index))), end; i != end; ++i)
        list.push_back(luabind::object_cast<ListType>(*i));

      return list;
    }

    void to(lua_State* L, const std::vector<ListType>& l) {
      luabind::object list = luabind::newtable(L);
      for (size_t i = 0; i < l.size(); ++i)
        list[i+1] = l[i];

      list.push(L);
    }
  };
}

class TestClass {
public:
  TestClass(std::vector<int> v) : m_vec(v) {}

  TestClass(int b, int e) {
    for (int i = b; i <= e; ++i)
      m_vec.push_back(i);
  }

  int get(size_t i) const {
    return m_vec[i];
  }

private:
  std::vector<int> m_vec;
};

int main(int argc, char** argv) {
  if (argc != 2) {
    cout << "usage: " << argv[0] << " <scriptname>" << endl;
    return -1;
  }

  std::string scriptName = argv[1];
  lua_State* L = (lua_State*) lua_open();
  luaL_openlibs(L);

  open(L);

  module(L)
  [
    class_<TestClass>("TestClass")
      .def(constructor<std::vector<int> >())
      .def(constructor<int, int>())
      .def("get", &TestClass::get)
  ];

  if (luaL_loadfile(L, scriptName.c_str()) || lua_pcall(L, 0, 0, 0)) {
    cout << "Script error: " << lua_tostring(L, -1) << endl;
    return -1;
  }

  call_function<void>(globals(L)["test"]);

  lua_close(L);
  return 0;
}
------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.