Luabind: Не може да върне shared_ptr

Опитвам се да върна std::shared_ptr от метод, свързан с Luabind, но изглежда не разпознава типа.

Код на Luabind:

module(lua)
[
    class_<Character, BaseEntity, std::shared_ptr<Character> > ("Character"),
        def("createCharacter", &Character::createCharacter)
];

createCharacter код:

std::shared_ptr<Character> Character::createCharacter(Game* gameInstance, const Character::CharacterSetup& characterSetup, string sprite, b2World* world)
{
    return std::shared_ptr<Character>(new Character(gameInstance, characterSetup, sprite, world));
}

Ако извикам този метод в Lua скрипт, нищо не се връща и изпълнението спира там. Ако обаче променя метода за връщане на символ *, той работи както се очаква. Някакво гугълване ми казва, че връщането на shared_ptr не би трябвало да е проблем.

какво правя грешно

Освен това имам този код, за да може Luabind да разбере std::shared_ptr:

namespace luabind
{
    template <typename T>
    T* get_pointer(std::shared_ptr<T> const& p)
    {
        return p.get();
    }
}

person tacospice    schedule 23.02.2013    source източник
comment
Опитахте ли boost::shared_ptr<T> вместо това?   -  person Luc Danton    schedule 23.02.2013
comment
Не съм много запознат с luabind, но ако не съхранява споделения указател, а просто използва get_pointer(), за да получи истински указател, той ще изпусне последната препратка (по този начин изтривайки обекта), докато запазва (сега висящ ) показалец. Първо, уверете се, че вашият клас е направен правилно и не може да се копира. Второ, добавете точки на прекъсване към конструктора и деструктора.   -  person Ulrich Eckhardt    schedule 23.02.2013


Отговори (1)


Трябваше да реша същия проблем.

Малко е сложно. По принцип трябва да дефинирате функция с прототипа

template <typename T>
T* get_pointer(std::shared_ptr<T> const&);

Тази функция допълнително трябва да се намира в същото пространство от имена като std::shared_ptr, следователно std::. Обърнете внимание, че функция в глобалното пространство от имена или luabind пространство от имена, като вашата, няма да работи, защото luabind използва специални трикове, за да се гарантира, че се използва само ADL, когато се проверява дали даден тип е интелигентен указател. Единственият начин да заобиколите това е да дефинирате вашата функция в пространството от имена luabind::detail::has_get_pointer_ вместо само luabind.

Но дефинирането на вашата функция само в това пространство от имена също няма да работи (поне за Boost ‹1.53). Въпреки че дефинирането на функцията в пространството от имена std технически не е позволено от C++-стандарта, това е единственият възможен начин за Boost ‹1.53. От 1.53 обаче Boost дефинира свои собствени boost::get_pointer() претоварвания за std::shared_ptrstd::unique_ptr). За тази версия е достатъчно да направите get_pointer() на Boost видим в пространството от имена luabind::detail::has_get_pointer_, тъй като luabind е using тази функция навсякъде, където използва интелигентни указатели (вижте luabind/get_pointer.hpp заглавка). Дефинирането на функцията в std дори няма да работи тогава, защото luabind би провокирало двусмислено извикване.

Така че, ако искате get_pointer() претоварване за std::shared_ptr, което работи за Boost ‹1.53 и >= 1.53, а също и за MSVC 10 (и може би 9) (те дефинират shared_ptr в std::tr1 вместо std), мога да ви предложа моя (исторически отгледан ;- ) ) заглавка:

#ifndef SHAREDPTR_CONVERTER_HPP_INCLUDED
#define SHAREDPTR_CONVERTER_HPP_INCLUDED SHAREDPTR_CONVERTER_HPP_INCLUDED

#include <boost/version.hpp>

#if BOOST_VERSION >= 105300

#include <boost/get_pointer.hpp>


namespace luabind { namespace detail { namespace has_get_pointer_ {
    template<class T>
    T * get_pointer(std::shared_ptr<T> const& p) { return p.get(); }
}}}

#else // if BOOST_VERSION < 105300

#include <memory>

// Not standard conforming: add function to ::std(::tr1)
namespace std {

#if defined(_MSC_VER) && _MSC_VER < 1700
namespace tr1 {
#endif

    template<class T>
    T * get_pointer(shared_ptr<T> const& p) { return p.get(); }

#if defined(_MSC_VER) && _MSC_VER < 1700
} // namespace tr1
#endif

} // namespace std

#endif // if BOOST_VERSION < 105300

#endif
person Oberon    schedule 04.03.2013
comment
страхотно страхотно страхотно. благодаря, благодаря, благодаря. - person morgancodes; 25.06.2014