当前位置: 动力学知识库 > 问答 > 编程问答 >

c++ - Luabind: Can't return shared_ptr

问题描述:

I'm trying to return an std::shared_ptr from a method bound with Luabind, but it doesn't seem to recognize the type.

Luabind code:

module(lua)

[

class_<Character, BaseEntity, std::shared_ptr<Character> > ("Character"),

def("createCharacter", &Character::createCharacter)

];

createCharacter code:

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));

}

If I call this method in a Lua script, nothing gets returned, and execution stops there. However, if I change the method to return a Character*, it works as expected. Some googling around tells me that returning a shared_ptr shouldn't be a problem.

What am I doing wrong?

Also, I have this code so Luabind can understand std::shared_ptr:

namespace luabind

{

template <typename T>

T* get_pointer(std::shared_ptr<T> const& p)

{

return p.get();

}

}

网友答案:

I had to solve the very same problem.

It's a bit complicated. Basically you need to define a function with the prototype

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

This function additionally must reside in the same namespace as std::shared_ptr, thus std::. Note that a function in the global namespace or luabind namespace, as yours, won't work, because luabind uses special tricks to ensure that only ADL is used when checking if a certain type is a smart pointer. The only way to circumvent this is to define your function in the luabind::detail::has_get_pointer_ namespace instead of just luabind.

But defining your function in this namespace alone, won't work either (at least for Boost <1.53). Although defining the function in namespace std is technically not allowed by the C++-standard, it is the only possible way for Boost <1.53. Since 1.53, however, Boost defines it's own boost::get_pointer() overloads for std::shared_ptr (and std::unique_ptr). For this version it's enough to make Boost's get_pointer() visible in the luabind::detail::has_get_pointer_ namespace, since luabind is using this function anywhere it uses smart pointers (see the luabind/get_pointer.hpp header). Defining the function in std wont even work then, because luabind would provoke an ambiguous call.

So if you want a get_pointer() overload for std::shared_ptr which works for Boost <1.53 and >= 1.53 and also for MSVC 10 (and maybe 9) (these define shared_ptr in std::tr1 instead of std), I can offer you my (historically grown ;-) ) header:

#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
分享给朋友:
您可能感兴趣的文章:
随机阅读: