luabind 0.9.1 использует итератор stl, показывает только один элемент - PullRequest
1 голос
/ 13 сентября 2011

У меня возникла странная проблема, когда я использовал luabind для возврата stl :: vector :: iterator в скрипт lua.

Ниже приведен код:

1) Я создал две функции, которые они вызывают скриптом lua:

std::vector<car*> get_car_list()
{
    std::vector<car*>* vec = new std::vector<car*>();
    vec->push_back(new car("I'm the 1st"));
    vec->push_back(new car("I'm the 2nd")); 
    return *vec;
}

void output(const std::string& msg)
{
    std::cout << "lua:" << msg << std::endl;
}

2) Я связываю функцию с lua

luabind::module(L)
[
    luabind::def("get_car_list", &get_car_list, luabind::return_stl_iterator)
];

luabind::module(L)
[
    luabind::def("output", &output)
];

3) Я делаю сценарий, как показано ниже:

function test()
    items  = get_car_list();
    for item in items do
        output(item:get_name());
    end
end

4) Результат: В окне вывода отображается только:

lua:I'm the 1st

И программа прерывается в luabind / policy.hpp: 754

template <>
struct default_converter<std::string>
  : native_converter_base<std::string>
{
    .....

    void to(lua_State* L, std::string const& value)
    {
        lua_pushlstring(L, value.data(), value.size()); // !!Break Here with Error EXC_BAD_ACCESS
    }
};

Я хочу отобразить все элементы в std :: vector, но он показывает только первый и вылетает.

Большое спасибо! :)

Jason

1 Ответ

3 голосов
/ 13 сентября 2011

Я вижу две проблемы:

Вы используете указатели и новые, как если бы мы были на Java, но это C ++.У вас будут явные утечки памяти, если вы будете использовать C ++ таким образом.

За исключением случаев, когда у вас есть конкретные причины, это должно быть:

std::vector<car> get_car_list() {
    std::vector<car> vec;
    vec->push_back( car("I'm the 1st"));
    vec->push_back( car("I'm the 2nd")); 
    return vec; }

Но возникает вторая проблема с вашим кодом:

Мне кажется, return_stl_iterator предполагает, что контейнер stl все еще существует, когда вы его используете, и сохраняет итератор в этом контейнере.

После этого вы не сможете вернуть копию контейнера так, как это делаете, потому чтоКонтейнер больше не будет существовать, когда вы захотите использовать итератор.Это как если бы вы использовали ссылку на временный контейнер.

Как видно из этого примера luabind doc , идея с return_stl_iterator состоит в том, чтобы иметь контейнер, который все еще доступен.В этом примере контейнер существует в структуре.Это не временно.

У вас может возникнуть соблазн выделить вектор с новым и вернуть ссылку на этот вектор в вашей функции get_car_list.Но не делайте этого: когда вы освободите свой контейнер?

Если вы хотите вернуть вектор, который не существует где-то еще (временная копия вектора), то вам не следует использовать return_stl_iteratorполитика, кажется, не для этого.

...