Luabind: 无法返回 shared_ptr。

我试图从一个绑定了 Luabind 的方法中返回一个 std::shared_ptr,但它似乎无法识别这个类型。

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 脚本中调用这个方法,什么都没有返回,执行就在这里停止了。然而,如果我将方法更改为返回 Character*,它就像预期的那样工作。一些关于谷歌的搜索告诉我,返回 shared_ptr 不应该有问题。

我做错了什么?

此外,我有这个代码,让 Luabind 可以理解 std::shared_ptr:

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

我不得不解决同样的问题。

这有点复杂。基本上,你需要定义原型为

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

的函数。此外,该函数必须和std::shared_ptr处于同一个命名空间中,也就是std::。注意,如果你将函数定义在全局命名空间或者luabind命名空间中,就像你现在的那样,是行不通的。因为luabind使用特殊技巧来确保只有使用ADL(Argument-dependent lookup)来检查某个类型是否为smart pointer(见has_get_pointer.hpp)。唯一的解决办法是在luabind::detail::has_get_pointer_命名空间中定义你的函数,而不是仅仅在luabind命名空间中。

但是,仅仅在luabind::detail::has_get_pointer_命名空间中定义你的函数是行不通的(至少对于Boost版本低于1.53的情况是这样)。虽然在std命名空间中定义函数在技术上不符合C++标准,但这是低于Boost 1.53的唯一可能的方法。然而,自1.53版本以来,Boost定义了自己的boost::get_pointer()重载,用于std::shared_ptr(以及std::unique_ptr)。对于这个版本,将Boost的get_pointer()可见于luabind::detail::has_get_pointer_命名空间就足够了,因为luabind在使用smart指针时会使用此函数(请查看luabind/get_pointer.hpp头文件)。在std中定义此函数甚至也行不通,因为luabind会引发一个二义性调用。

因此,如果你想要在Boost <1.53和>= 1.53以及MSVC 10(和可能是9)(这些在std::tr1而不是std中定义shared_ptr)中使用std::shared_ptrget_pointer()重载,我可以提供我的(有历史以来的;-))头文件:

#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
2013-03-04 17:50:04