cppbind: fix Ghost casting/storage in polymorphic class hierarchies.
This commit is contained in:
@@ -3,6 +3,7 @@ include (SimGearComponent)
|
|||||||
set(HEADERS
|
set(HEADERS
|
||||||
Ghost.hxx
|
Ghost.hxx
|
||||||
NasalCallContext.hxx
|
NasalCallContext.hxx
|
||||||
|
NasalContext.hxx
|
||||||
NasalHash.hxx
|
NasalHash.hxx
|
||||||
NasalObject.hxx
|
NasalObject.hxx
|
||||||
NasalObjectHolder.hxx
|
NasalObjectHolder.hxx
|
||||||
@@ -21,6 +22,7 @@ set(DETAIL_HEADERS
|
|||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
Ghost.cxx
|
Ghost.cxx
|
||||||
|
NasalContext.cxx
|
||||||
NasalHash.cxx
|
NasalHash.cxx
|
||||||
NasalString.cxx
|
NasalString.cxx
|
||||||
NasalObject.cxx
|
NasalObject.cxx
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace nasal
|
|||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
bool GhostMetadata::isBaseOf(naGhostType* ghost_type, bool& is_weak) const
|
bool GhostMetadata::isInstance(naGhostType* ghost_type, bool& is_weak) const
|
||||||
{
|
{
|
||||||
if( ghost_type == _ghost_type_strong_ptr )
|
if( ghost_type == _ghost_type_strong_ptr )
|
||||||
{
|
{
|
||||||
@@ -47,14 +47,6 @@ namespace nasal
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( DerivedList::const_iterator derived = _derived_classes.begin();
|
|
||||||
derived != _derived_classes.end();
|
|
||||||
++derived )
|
|
||||||
{
|
|
||||||
if( (*derived)->isBaseOf(ghost_type, is_weak) )
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +66,6 @@ namespace nasal
|
|||||||
void GhostMetadata::addDerived(const GhostMetadata* derived)
|
void GhostMetadata::addDerived(const GhostMetadata* derived)
|
||||||
{
|
{
|
||||||
assert(derived);
|
assert(derived);
|
||||||
_derived_classes.push_back(derived);
|
|
||||||
|
|
||||||
SG_LOG
|
SG_LOG
|
||||||
(
|
(
|
||||||
|
|||||||
+131
-70
@@ -107,17 +107,14 @@ namespace nasal
|
|||||||
*/
|
*/
|
||||||
void addNasalBase(const naRef& parent);
|
void addNasalBase(const naRef& parent);
|
||||||
|
|
||||||
bool isBaseOf(naGhostType* ghost_type, bool& is_weak) const;
|
bool isInstance(naGhostType* ghost_type, bool& is_weak) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
typedef std::vector<const GhostMetadata*> DerivedList;
|
|
||||||
|
|
||||||
const std::string _name_strong,
|
const std::string _name_strong,
|
||||||
_name_weak;
|
_name_weak;
|
||||||
const naGhostType *_ghost_type_strong_ptr,
|
const naGhostType *_ghost_type_strong_ptr,
|
||||||
*_ghost_type_weak_ptr;
|
*_ghost_type_weak_ptr;
|
||||||
DerivedList _derived_classes;
|
|
||||||
std::vector<naRef> _parents;
|
std::vector<naRef> _parents;
|
||||||
|
|
||||||
GhostMetadata( const std::string& name,
|
GhostMetadata( const std::string& name,
|
||||||
@@ -307,7 +304,7 @@ namespace nasal
|
|||||||
|
|
||||||
// Keep reference for duration of call to prevent expiring
|
// Keep reference for duration of call to prevent expiring
|
||||||
// TODO not needed for strong referenced ghost
|
// TODO not needed for strong referenced ghost
|
||||||
strong_ref ref = fromNasal<strong_ref>(c, me);
|
strong_ref ref = fromNasal(c, me);
|
||||||
if( !ref )
|
if( !ref )
|
||||||
{
|
{
|
||||||
naGhostType* ghost_type = naGhost_type(me);
|
naGhostType* ghost_type = naGhost_type(me);
|
||||||
@@ -416,10 +413,13 @@ namespace nasal
|
|||||||
boost::is_base_of<typename BaseGhost::raw_type, raw_type>::value
|
boost::is_base_of<typename BaseGhost::raw_type, raw_type>::value
|
||||||
));
|
));
|
||||||
|
|
||||||
|
typedef typename BaseGhost::strong_ref base_ref;
|
||||||
|
|
||||||
BaseGhost* base = BaseGhost::getSingletonPtr();
|
BaseGhost* base = BaseGhost::getSingletonPtr();
|
||||||
base->addDerived(
|
base->addDerived(
|
||||||
this,
|
this,
|
||||||
SG_GET_TEMPLATE_MEMBER(Ghost, getTypeFor<BaseGhost>)
|
SG_GET_TEMPLATE_MEMBER(Ghost, toNasal<BaseGhost>),
|
||||||
|
SG_GET_TEMPLATE_MEMBER(Ghost, fromNasalWithCast<base_ref>)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Replace any getter that is not available in the current class.
|
// Replace any getter that is not available in the current class.
|
||||||
@@ -809,7 +809,7 @@ namespace nasal
|
|||||||
makeGhost(naContext c, RefType const& ref_ptr)
|
makeGhost(naContext c, RefType const& ref_ptr)
|
||||||
{
|
{
|
||||||
strong_ref ref(ref_ptr);
|
strong_ref ref(ref_ptr);
|
||||||
raw_type* ptr = get_pointer(ref_ptr);
|
raw_type* ptr = get_pointer(ref);
|
||||||
if( !ptr )
|
if( !ptr )
|
||||||
return naNil();
|
return naNil();
|
||||||
|
|
||||||
@@ -817,15 +817,11 @@ namespace nasal
|
|||||||
// will then be hold be a new shared pointer. We therefore have to
|
// will then be hold be a new shared pointer. We therefore have to
|
||||||
// check for the dynamic type of the object as it might differ from
|
// check for the dynamic type of the object as it might differ from
|
||||||
// the passed static type.
|
// the passed static type.
|
||||||
naGhostType* ghost_type =
|
return toNasal<Ghost>(
|
||||||
getTypeFor<Ghost>(ptr, shared_ptr_traits<RefType>::is_strong::value);
|
c,
|
||||||
|
ref,
|
||||||
if( !ghost_type )
|
shared_ptr_traits<RefType>::is_strong::value
|
||||||
return naNil();
|
);
|
||||||
|
|
||||||
return naNewGhost2( c,
|
|
||||||
ghost_type,
|
|
||||||
shared_ptr_storage<RefType>::ref(ref_ptr) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -833,25 +829,36 @@ namespace nasal
|
|||||||
* Nasal objects has to be derived class of the target class (Either
|
* Nasal objects has to be derived class of the target class (Either
|
||||||
* derived in C++ or in Nasal using a 'parents' vector)
|
* derived in C++ or in Nasal using a 'parents' vector)
|
||||||
*/
|
*/
|
||||||
template<class Type>
|
static strong_ref fromNasal(naContext c, naRef me)
|
||||||
static Type fromNasal(naContext c, naRef me)
|
|
||||||
{
|
{
|
||||||
bool is_weak = false;
|
naGhostType* ghost_type = naGhost_type(me);
|
||||||
|
if( ghost_type )
|
||||||
// Check if it's a ghost and if it can be converted
|
|
||||||
if( isBaseOf(naGhost_type(me), is_weak) )
|
|
||||||
{
|
{
|
||||||
void* ghost = naGhost_ptr(me);
|
// Check if we got an instance of this class
|
||||||
return is_weak ? getPtr<Type, true>(ghost)
|
bool is_weak = false;
|
||||||
: getPtr<Type, false>(ghost);
|
if( isInstance(ghost_type, is_weak) )
|
||||||
}
|
{
|
||||||
|
return is_weak ? getPtr<strong_ref, true>(naGhost_ptr(me))
|
||||||
|
: getPtr<strong_ref, false>(naGhost_ptr(me));
|
||||||
|
}
|
||||||
|
|
||||||
// Now if it is derived from a ghost (hash with ghost in parent vector)
|
// otherwise try the derived classes
|
||||||
|
for( typename DerivedList::reverse_iterator
|
||||||
|
derived = getSingletonPtr()->_derived_types.rbegin();
|
||||||
|
derived != getSingletonPtr()->_derived_types.rend();
|
||||||
|
++derived )
|
||||||
|
{
|
||||||
|
strong_ref ref = (derived->from_nasal)(c, me);
|
||||||
|
|
||||||
|
if( get_pointer(ref) )
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if( naIsHash(me) )
|
else if( naIsHash(me) )
|
||||||
{
|
{
|
||||||
naRef na_parents = naHash_cget(me, const_cast<char*>("parents"));
|
naRef na_parents = naHash_cget(me, const_cast<char*>("parents"));
|
||||||
if( !naIsVector(na_parents) )
|
if( !naIsVector(na_parents) )
|
||||||
return Type();
|
return strong_ref();
|
||||||
|
|
||||||
typedef std::vector<naRef> naRefs;
|
typedef std::vector<naRef> naRefs;
|
||||||
naRefs parents = from_nasal<naRefs>(c, na_parents);
|
naRefs parents = from_nasal<naRefs>(c, na_parents);
|
||||||
@@ -859,19 +866,13 @@ namespace nasal
|
|||||||
parent != parents.end();
|
parent != parents.end();
|
||||||
++parent )
|
++parent )
|
||||||
{
|
{
|
||||||
Type ptr = fromNasal<Type>(c, *parent);
|
strong_ref ref = fromNasal(c, *parent);
|
||||||
if( get_pointer(ptr) )
|
if( get_pointer(ref) )
|
||||||
return ptr;
|
return ref;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Type();
|
return strong_ref();
|
||||||
}
|
|
||||||
|
|
||||||
static bool isBaseOf(naRef obj)
|
|
||||||
{
|
|
||||||
bool is_weak;
|
|
||||||
return isBaseOf(naGhost_type(obj), is_weak);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -882,21 +883,30 @@ namespace nasal
|
|||||||
static naGhostType _ghost_type_strong, //!< Stored as shared pointer
|
static naGhostType _ghost_type_strong, //!< Stored as shared pointer
|
||||||
_ghost_type_weak; //!< Stored as weak shared pointer
|
_ghost_type_weak; //!< Stored as weak shared pointer
|
||||||
|
|
||||||
typedef naGhostType* (*type_checker_t)(const raw_type*, bool);
|
typedef naRef (*to_nasal_t)(naContext, const strong_ref&, bool);
|
||||||
typedef std::vector<type_checker_t> DerivedList;
|
typedef strong_ref (*from_nasal_t)(naContext, naRef);
|
||||||
|
struct DerivedInfo
|
||||||
|
{
|
||||||
|
to_nasal_t to_nasal;
|
||||||
|
from_nasal_t from_nasal;
|
||||||
|
|
||||||
|
DerivedInfo( to_nasal_t to_nasal_func,
|
||||||
|
from_nasal_t from_nasal_func ):
|
||||||
|
to_nasal(to_nasal_func),
|
||||||
|
from_nasal(from_nasal_func)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<DerivedInfo> DerivedList;
|
||||||
DerivedList _derived_types;
|
DerivedList _derived_types;
|
||||||
|
|
||||||
static bool isBaseOf(naGhostType* ghost_type, bool& is_weak)
|
static bool isInstance(naGhostType* ghost_type, bool& is_weak)
|
||||||
{
|
{
|
||||||
if( !ghost_type || !getSingletonPtr() )
|
if( !ghost_type || !getSingletonPtr() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return getSingletonPtr()->GhostMetadata::isBaseOf(ghost_type, is_weak);
|
return getSingletonPtr()->GhostMetadata::isInstance( ghost_type,
|
||||||
}
|
is_weak );
|
||||||
|
|
||||||
static bool isBaseOf(naRef obj, bool& is_weak)
|
|
||||||
{
|
|
||||||
return isBaseOf(naGhost_type(obj), is_weak);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RefPtr, bool is_weak>
|
template<class RefPtr, bool is_weak>
|
||||||
@@ -945,28 +955,33 @@ namespace nasal
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addDerived( const internal::GhostMetadata* derived_meta,
|
void addDerived( const internal::GhostMetadata* derived_meta,
|
||||||
type_checker_t derived_type_checker )
|
to_nasal_t to_nasal_func,
|
||||||
|
from_nasal_t from_nasal_func )
|
||||||
{
|
{
|
||||||
GhostMetadata::addDerived(derived_meta);
|
GhostMetadata::addDerived(derived_meta);
|
||||||
_derived_types.push_back(derived_type_checker);
|
_derived_types.push_back(DerivedInfo(to_nasal_func, from_nasal_func));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class BaseGhost>
|
template<class BaseGhost>
|
||||||
static
|
static
|
||||||
typename boost::enable_if
|
typename boost::enable_if
|
||||||
< boost::is_polymorphic<typename BaseGhost::raw_type>,
|
< boost::is_polymorphic<typename BaseGhost::raw_type>,
|
||||||
naGhostType*
|
naRef
|
||||||
>::type
|
>::type
|
||||||
getTypeFor(const typename BaseGhost::raw_type* base, bool strong)
|
toNasal( naContext c,
|
||||||
|
const typename BaseGhost::strong_ref& base_ref,
|
||||||
|
bool strong )
|
||||||
{
|
{
|
||||||
|
typename BaseGhost::raw_type* ptr = get_pointer(base_ref);
|
||||||
|
|
||||||
// Check first if passed pointer can by converted to instance of class
|
// Check first if passed pointer can by converted to instance of class
|
||||||
// this ghost wraps.
|
// this ghost wraps.
|
||||||
if( !boost::is_same
|
if( !boost::is_same
|
||||||
< typename BaseGhost::raw_type,
|
< typename BaseGhost::raw_type,
|
||||||
typename Ghost::raw_type
|
typename Ghost::raw_type
|
||||||
>::value
|
>::value
|
||||||
&& dynamic_cast<const typename Ghost::raw_type*>(base) != base )
|
&& dynamic_cast<const typename Ghost::raw_type*>(ptr) != ptr )
|
||||||
return 0;
|
return naNil();
|
||||||
|
|
||||||
if( !getSingletonPtr() )
|
if( !getSingletonPtr() )
|
||||||
{
|
{
|
||||||
@@ -976,45 +991,52 @@ namespace nasal
|
|||||||
SG_INFO,
|
SG_INFO,
|
||||||
"Ghost::getTypeFor: can not get type for unregistered ghost"
|
"Ghost::getTypeFor: can not get type for unregistered ghost"
|
||||||
);
|
);
|
||||||
return 0;
|
return naNil();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strong_ref ref =
|
||||||
|
static_pointer_cast<typename Ghost::raw_type>(base_ref);
|
||||||
|
|
||||||
// Now check if we can further downcast to one of our derived classes.
|
// Now check if we can further downcast to one of our derived classes.
|
||||||
for( typename DerivedList::reverse_iterator
|
for( typename DerivedList::reverse_iterator
|
||||||
derived = getSingletonPtr()->_derived_types.rbegin();
|
derived = getSingletonPtr()->_derived_types.rbegin();
|
||||||
derived != getSingletonPtr()->_derived_types.rend();
|
derived != getSingletonPtr()->_derived_types.rend();
|
||||||
++derived )
|
++derived )
|
||||||
{
|
{
|
||||||
naGhostType* ghost_type =
|
naRef ghost = (derived->to_nasal)(c, ref, strong);
|
||||||
(*derived)(
|
|
||||||
static_cast<const typename Ghost::raw_type*>(base),
|
|
||||||
strong
|
|
||||||
);
|
|
||||||
|
|
||||||
if( ghost_type )
|
if( !naIsNil(ghost) )
|
||||||
return ghost_type;
|
return ghost;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If base is not an instance of any derived class, this class has to
|
// If base is not an instance of any derived class, this class has to
|
||||||
// be the dynamic type.
|
// be the dynamic type.
|
||||||
return strong
|
return strong
|
||||||
? &_ghost_type_strong
|
? create<false>(c, ref)
|
||||||
: &_ghost_type_weak;
|
: create<true>(c, ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class BaseGhost>
|
template<class BaseGhost>
|
||||||
static
|
static
|
||||||
typename boost::disable_if
|
typename boost::disable_if
|
||||||
< boost::is_polymorphic<typename BaseGhost::raw_type>,
|
< boost::is_polymorphic<typename BaseGhost::raw_type>,
|
||||||
naGhostType*
|
naRef
|
||||||
>::type
|
>::type
|
||||||
getTypeFor(const typename BaseGhost::raw_type* base, bool strong)
|
toNasal( naContext c,
|
||||||
|
const typename BaseGhost::strong_ref& ref,
|
||||||
|
bool strong )
|
||||||
{
|
{
|
||||||
// For non polymorphic classes there is no possibility to get the actual
|
// For non polymorphic classes there is no possibility to get the actual
|
||||||
// dynamic type, therefore we can only use its static type.
|
// dynamic type, therefore we can only use its static type.
|
||||||
return strong
|
return strong
|
||||||
? &BaseGhost::_ghost_type_strong
|
? create<false>(c, ref)
|
||||||
: &BaseGhost::_ghost_type_weak;
|
: create<true>(c, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
static Type fromNasalWithCast(naContext c, naRef me)
|
||||||
|
{
|
||||||
|
return Type(fromNasal(c, me));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Ghost* getSingletonPtr()
|
static Ghost* getSingletonPtr()
|
||||||
@@ -1176,6 +1198,45 @@ namespace nasal
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<bool is_weak>
|
||||||
|
static
|
||||||
|
typename boost::enable_if_c<
|
||||||
|
!is_weak,
|
||||||
|
naRef
|
||||||
|
>::type
|
||||||
|
create(naContext c, const strong_ref& ref_ptr)
|
||||||
|
{
|
||||||
|
typedef shared_ptr_storage<strong_ref> storage_type;
|
||||||
|
return naNewGhost2( c,
|
||||||
|
&Ghost::_ghost_type_strong,
|
||||||
|
storage_type::ref(ref_ptr) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool is_weak>
|
||||||
|
static
|
||||||
|
typename boost::enable_if_c<
|
||||||
|
is_weak && supports_weak_ref<T>::value,
|
||||||
|
naRef
|
||||||
|
>::type
|
||||||
|
create(naContext c, const strong_ref& ref_ptr)
|
||||||
|
{
|
||||||
|
typedef shared_ptr_storage<weak_ref> storage_type;
|
||||||
|
return naNewGhost2( c,
|
||||||
|
&Ghost::_ghost_type_weak,
|
||||||
|
storage_type::ref(ref_ptr) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool is_weak>
|
||||||
|
static
|
||||||
|
typename boost::enable_if_c<
|
||||||
|
is_weak && !supports_weak_ref<T>::value,
|
||||||
|
naRef
|
||||||
|
>::type
|
||||||
|
create(naContext, const strong_ref&)
|
||||||
|
{
|
||||||
|
return naNil();
|
||||||
|
}
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
static void destroy(void *ptr)
|
static void destroy(void *ptr)
|
||||||
{
|
{
|
||||||
@@ -1354,7 +1415,7 @@ typename boost::enable_if<
|
|||||||
from_nasal_helper(naContext c, naRef ref, const T*)
|
from_nasal_helper(naContext c, naRef ref, const T*)
|
||||||
{
|
{
|
||||||
typedef typename nasal::shared_ptr_traits<T>::strong_ref strong_ref;
|
typedef typename nasal::shared_ptr_traits<T>::strong_ref strong_ref;
|
||||||
return nasal::Ghost<strong_ref>::template fromNasal<T>(c, ref);
|
return T(nasal::Ghost<strong_ref>::fromNasal(c, ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1389,7 +1450,7 @@ typename boost::enable_if_c<
|
|||||||
from_nasal_helper(naContext c, naRef ref, const T*)
|
from_nasal_helper(naContext c, naRef ref, const T*)
|
||||||
{
|
{
|
||||||
typedef SGSharedPtr<typename boost::remove_pointer<T>::type> TypeRef;
|
typedef SGSharedPtr<typename boost::remove_pointer<T>::type> TypeRef;
|
||||||
return nasal::Ghost<TypeRef>::template fromNasal<T>(c, ref);
|
return T(nasal::Ghost<TypeRef>::fromNasal(c, ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1416,7 +1477,7 @@ typename boost::enable_if<
|
|||||||
from_nasal_helper(naContext c, naRef ref, const T*)
|
from_nasal_helper(naContext c, naRef ref, const T*)
|
||||||
{
|
{
|
||||||
typedef osg::ref_ptr<typename boost::remove_pointer<T>::type> TypeRef;
|
typedef osg::ref_ptr<typename boost::remove_pointer<T>::type> TypeRef;
|
||||||
return nasal::Ghost<TypeRef>::template fromNasal<T>(c, ref);
|
return T(nasal::Ghost<TypeRef>::fromNasal(c, ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SG_NASAL_GHOST_HXX_ */
|
#endif /* SG_NASAL_GHOST_HXX_ */
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// Manage lifetime and encapsulate a Nasal context
|
||||||
|
//
|
||||||
|
// Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Library General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Library General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Library General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
#include "NasalContext.hxx"
|
||||||
|
|
||||||
|
namespace nasal
|
||||||
|
{
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
Context::Context():
|
||||||
|
_ctx(naNewContext())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
Context::~Context()
|
||||||
|
{
|
||||||
|
naFreeContext(_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
Context::operator naContext()
|
||||||
|
{
|
||||||
|
return _ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
Hash Context::newHash()
|
||||||
|
{
|
||||||
|
return Hash(_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nasal
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
///@file Manage lifetime and encapsulate a Nasal context
|
||||||
|
//
|
||||||
|
// Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Library General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Library General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Library General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
#ifndef SG_NASAL_CONTEXT_HXX_
|
||||||
|
#define SG_NASAL_CONTEXT_HXX_
|
||||||
|
|
||||||
|
#include "NasalHash.hxx"
|
||||||
|
|
||||||
|
namespace nasal
|
||||||
|
{
|
||||||
|
|
||||||
|
class Context
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Context();
|
||||||
|
~Context();
|
||||||
|
|
||||||
|
operator naContext();
|
||||||
|
|
||||||
|
Hash newHash();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
naContext _ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nasal
|
||||||
|
|
||||||
|
#endif /* SG_NASAL_CONTEXT_HXX_ */
|
||||||
@@ -322,10 +322,6 @@ int main(int argc, char* argv[])
|
|||||||
== ref_based.get() );
|
== ref_based.get() );
|
||||||
VERIFY( from_nasal<SGRefBasedPtr>(c, na_ref_based) == ref_based );
|
VERIFY( from_nasal<SGRefBasedPtr>(c, na_ref_based) == ref_based );
|
||||||
|
|
||||||
VERIFY( Ghost<BasePtr>::isBaseOf(derived) );
|
|
||||||
VERIFY( Ghost<DerivedPtr>::isBaseOf(derived) );
|
|
||||||
VERIFY( Ghost<DoubleDerived2Ptr>::isBaseOf(derived) );
|
|
||||||
|
|
||||||
VERIFY( from_nasal<BasePtr>(c, derived) == d3 );
|
VERIFY( from_nasal<BasePtr>(c, derived) == d3 );
|
||||||
VERIFY( from_nasal<BasePtr>(c, derived) != d2 );
|
VERIFY( from_nasal<BasePtr>(c, derived) != d2 );
|
||||||
VERIFY( from_nasal<DerivedPtr>(c, derived)
|
VERIFY( from_nasal<DerivedPtr>(c, derived)
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#include <BoostTestTargetConfig.h>
|
#include <BoostTestTargetConfig.h>
|
||||||
|
|
||||||
#include "Ghost.hxx"
|
#include "Ghost.hxx"
|
||||||
|
#include "NasalContext.hxx"
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/weak_ptr.hpp>
|
#include <boost/weak_ptr.hpp>
|
||||||
|
|
||||||
@@ -49,14 +51,19 @@ BOOST_STATIC_ASSERT(( nasal::supports_weak_ref<DerivedPtr>::value));
|
|||||||
BOOST_STATIC_ASSERT(( nasal::supports_weak_ref<DerivedWeakPtr>::value));
|
BOOST_STATIC_ASSERT(( nasal::supports_weak_ref<DerivedWeakPtr>::value));
|
||||||
BOOST_STATIC_ASSERT((!nasal::supports_weak_ref<SGReferencedPtr>::value));
|
BOOST_STATIC_ASSERT((!nasal::supports_weak_ref<SGReferencedPtr>::value));
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( ghost_weak_strong_nasal_conversion )
|
static void setupGhosts()
|
||||||
{
|
{
|
||||||
nasal::Ghost<Base1Ptr>::init("Base1");
|
nasal::Ghost<Base1Ptr>::init("Base1");
|
||||||
nasal::Ghost<Base2Ptr>::init("Base2");
|
nasal::Ghost<Base2Ptr>::init("Base2");
|
||||||
nasal::Ghost<DerivedPtr>::init("Derived")
|
nasal::Ghost<DerivedPtr>::init("Derived")
|
||||||
.bases<Base1Ptr>()
|
.bases<Base1Ptr>()
|
||||||
.bases<Base2Ptr>();
|
.bases<Base2Ptr>();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
BOOST_AUTO_TEST_CASE( ghost_weak_strong_nasal_conversion )
|
||||||
|
{
|
||||||
|
setupGhosts();
|
||||||
naContext c = naNewContext();
|
naContext c = naNewContext();
|
||||||
|
|
||||||
DerivedPtr d = new Derived();
|
DerivedPtr d = new Derived();
|
||||||
@@ -91,6 +98,45 @@ BOOST_AUTO_TEST_CASE( ghost_weak_strong_nasal_conversion )
|
|||||||
BOOST_REQUIRE( !weak.lock() );
|
BOOST_REQUIRE( !weak.lock() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
BOOST_AUTO_TEST_CASE( ghost_casting_storage )
|
||||||
|
{
|
||||||
|
setupGhosts();
|
||||||
|
nasal::Context c;
|
||||||
|
|
||||||
|
// Check converting to and from every class in the hierarchy for an instance
|
||||||
|
// of the leaf class
|
||||||
|
DerivedPtr d = new Derived();
|
||||||
|
|
||||||
|
naRef na_d = nasal::to_nasal(c, d),
|
||||||
|
na_b1 = nasal::to_nasal(c, Base1Ptr(d)),
|
||||||
|
na_b2 = nasal::to_nasal(c, Base2Ptr(d));
|
||||||
|
|
||||||
|
Derived *d0 = nasal::from_nasal<Derived*>(c, na_d),
|
||||||
|
*d1 = nasal::from_nasal<Derived*>(c, na_b1),
|
||||||
|
*d2 = nasal::from_nasal<Derived*>(c, na_b2);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(d0, d.get());
|
||||||
|
BOOST_CHECK_EQUAL(d1, d.get());
|
||||||
|
BOOST_CHECK_EQUAL(d2, d.get());
|
||||||
|
|
||||||
|
Base1 *b1 = nasal::from_nasal<Base1*>(c, na_b1);
|
||||||
|
BOOST_CHECK_EQUAL(b1, static_cast<Base1*>(d.get()));
|
||||||
|
|
||||||
|
Base2 *b2 = nasal::from_nasal<Base2*>(c, na_b2);
|
||||||
|
BOOST_CHECK_EQUAL(b2, static_cast<Base2*>(d.get()));
|
||||||
|
|
||||||
|
// Check converting from base class instance to derived classes is not
|
||||||
|
// possible
|
||||||
|
Base1Ptr b1_ref = new Base1();
|
||||||
|
na_b1 = nasal::to_nasal(c, b1_ref);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(nasal::from_nasal<Base1*>(c, na_b1), b1_ref.get());
|
||||||
|
BOOST_CHECK(!nasal::from_nasal<Base2*>(c, na_b1));
|
||||||
|
BOOST_CHECK(!nasal::from_nasal<Derived*>(c, na_b1));
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
#define CHECK_PTR_STORAGE_TRAIT_TYPE(ptr_t, storage)\
|
#define CHECK_PTR_STORAGE_TRAIT_TYPE(ptr_t, storage)\
|
||||||
BOOST_STATIC_ASSERT((boost::is_same<\
|
BOOST_STATIC_ASSERT((boost::is_same<\
|
||||||
nasal::shared_ptr_storage<ptr_t>::storage_type,\
|
nasal::shared_ptr_storage<ptr_t>::storage_type,\
|
||||||
|
|||||||
Reference in New Issue
Block a user