From Marco Jez, "Problems fixed:
1. type converters created automatically by the I_BaseType macro use static_cast<> even for base-to-derived conversions. dynamic_cast<> should be used instead. 2. as a consequence of the above fix, I_BaseType must now differentiate between polymorphic and non-polymorphic base classes, because the latter can't be dynamic_cast'd to derived classes. Some template magic (see is_polymorphic<> in ReflectionMacros) is used to detect polymorphism at compile time (I'm NOT sure it works on all platforms as it's partly implementation-dependent. Please test!). 3. predefined custom property getters/setters/counters/etc. (as those defined for STL containers) only work on Value objects that contain non-pointer instances. This was an unwanted restriction that no longer exists. Wrappers will need to be recompiled. This is a good time to give them a fresh update with genwrapper. NOTE: fix #1 should get rid of those crashes and strange behaviours that some users noticed while using osgIntrospection through osgTcl or in their own code."
This commit is contained in:
@@ -21,6 +21,25 @@
|
||||
#include <osgIntrospection/ConverterProxy>
|
||||
#include <osgIntrospection/Converter>
|
||||
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
/** Compile-time polymorphism detector.
|
||||
The enumeration constant "value" evaluates
|
||||
to true only if T is a polymorphic class,
|
||||
false otherwise. T must be a subclassable
|
||||
type.
|
||||
*/
|
||||
template<typename T>
|
||||
struct is_polymorphic
|
||||
{
|
||||
class dummy1: public T { ~dummy1(); };
|
||||
class dummy2: public T { virtual ~dummy2(); };
|
||||
enum { value = sizeof(dummy1) == sizeof(dummy2) };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// "private" macros, not to be used outside this file
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -145,31 +164,49 @@
|
||||
#define I_ReaderWriter(x) setReaderWriter(new x);
|
||||
#define I_Comparator(x) setComparator(new x);
|
||||
|
||||
template<typename x, typename reflected_type, bool polymorphic>
|
||||
struct BaseTypeConverters
|
||||
{
|
||||
BaseTypeConverters()
|
||||
{
|
||||
const osgIntrospection::Type& st = typeof(reflected_type*); \
|
||||
const osgIntrospection::Type& cst = typeof(const reflected_type*); \
|
||||
const osgIntrospection::Type& dt = typeof(x*); \
|
||||
const osgIntrospection::Type& cdt = typeof(const x*); \
|
||||
osgIntrospection::ConverterProxy cp1(st, dt, new osgIntrospection::StaticConverter<reflected_type* , x*>); \
|
||||
osgIntrospection::ConverterProxy cp2(cst, cdt, new osgIntrospection::StaticConverter<const reflected_type* , const x*>); \
|
||||
osgIntrospection::ConverterProxy cp1c(st, cdt, new osgIntrospection::StaticConverter<reflected_type* , const x*>); \
|
||||
}
|
||||
};
|
||||
|
||||
template<typename x, typename reflected_type>
|
||||
struct BaseTypeConverters<x, reflected_type, true>
|
||||
{
|
||||
BaseTypeConverters()
|
||||
{
|
||||
const osgIntrospection::Type& st = typeof(reflected_type*); \
|
||||
const osgIntrospection::Type& cst = typeof(const reflected_type*); \
|
||||
const osgIntrospection::Type& dt = typeof(x*); \
|
||||
const osgIntrospection::Type& cdt = typeof(const x*); \
|
||||
osgIntrospection::ConverterProxy cp1(st, dt, new osgIntrospection::StaticConverter<reflected_type* , x*>); \
|
||||
osgIntrospection::ConverterProxy cp2(cst, cdt, new osgIntrospection::StaticConverter<const reflected_type* , const x*>); \
|
||||
osgIntrospection::ConverterProxy cp1c(st, cdt, new osgIntrospection::StaticConverter<reflected_type* , const x*>); \
|
||||
osgIntrospection::ConverterProxy cp3(dt, st, new osgIntrospection::DynamicConverter<x*, reflected_type* >); \
|
||||
osgIntrospection::ConverterProxy cp4(cdt, cst, new osgIntrospection::DynamicConverter<const x*, const reflected_type* >); \
|
||||
osgIntrospection::ConverterProxy cp3c(dt, cst, new osgIntrospection::DynamicConverter<x*, const reflected_type* >); \
|
||||
}
|
||||
};
|
||||
|
||||
#define I_BaseType(x) \
|
||||
{ \
|
||||
addBaseType(typeof(x)); \
|
||||
const osgIntrospection::Type& st = typeof(reflected_type* ); \
|
||||
const osgIntrospection::Type& cst = typeof(const reflected_type* ); \
|
||||
const osgIntrospection::Type& dt = typeof(x *); \
|
||||
const osgIntrospection::Type& cdt = typeof(const x *); \
|
||||
osgIntrospection::ConverterProxy cp1(st, dt, new osgIntrospection::StaticConverter<reflected_type* , x *>); \
|
||||
osgIntrospection::ConverterProxy cp2(cst, cdt, new osgIntrospection::StaticConverter<const reflected_type* , const x *>); \
|
||||
osgIntrospection::ConverterProxy cp1c(st, cdt, new osgIntrospection::StaticConverter<reflected_type* , const x *>); \
|
||||
osgIntrospection::ConverterProxy cp3(dt, st, new osgIntrospection::StaticConverter<x *, reflected_type* >); \
|
||||
osgIntrospection::ConverterProxy cp4(cdt, cst, new osgIntrospection::StaticConverter<const x *, const reflected_type* >); \
|
||||
osgIntrospection::ConverterProxy cp3c(dt, cst, new osgIntrospection::StaticConverter<x *, const reflected_type* >); \
|
||||
addBaseType(typeof(x )); \
|
||||
BaseTypeConverters<x, reflected_type, osgIntrospection::is_polymorphic<x >::value> btc; \
|
||||
}
|
||||
|
||||
#define I_VirtualBaseType(x) \
|
||||
{ \
|
||||
addBaseType(typeof(x)); \
|
||||
const osgIntrospection::Type& st = typeof(reflected_type* ); \
|
||||
const osgIntrospection::Type& cst = typeof(const reflected_type* ); \
|
||||
const osgIntrospection::Type& dt = typeof(x *); \
|
||||
const osgIntrospection::Type& cdt = typeof(const x *); \
|
||||
osgIntrospection::ConverterProxy cp1(st, dt, new osgIntrospection::StaticConverter<reflected_type* , x *>); \
|
||||
osgIntrospection::ConverterProxy cp2(cst, cdt, new osgIntrospection::StaticConverter<const reflected_type* , const x *>); \
|
||||
osgIntrospection::ConverterProxy cp1c(st, cdt, new osgIntrospection::StaticConverter<reflected_type* , const x *>); \
|
||||
addBaseType(typeof(x )); \
|
||||
BaseTypeConverters<x, reflected_type, false> btc; \
|
||||
}
|
||||
|
||||
#define I_EnumLabel(x) addEnumLabel(x, #x, true);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <osgIntrospection/ReaderWriter>
|
||||
#include <osgIntrospection/TypedConstructorInfo>
|
||||
#include <osgIntrospection/Comparator>
|
||||
#include <osgIntrospection/Utility>
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
@@ -104,7 +105,7 @@ namespace osgIntrospection
|
||||
|
||||
/// Sets the current type's ReaderWriter object.
|
||||
void setReaderWriter(const ReaderWriter* rw);
|
||||
|
||||
|
||||
private:
|
||||
struct PtrConstructor: ConstructorInfo
|
||||
{
|
||||
@@ -263,14 +264,12 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual Value get(Value& instance, int i) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
return ctr.at(i);
|
||||
return getInstance<T>(instance).at(i);
|
||||
}
|
||||
|
||||
virtual Value get(const Value& instance, int i) const
|
||||
{
|
||||
const T& ctr = variant_cast<const T& >(instance);
|
||||
return ctr.at(i);
|
||||
return getInstance<T>(instance).at(i);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -278,8 +277,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual void set(Value& instance, int i, const Value& v) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
ctr.at(i) = variant_cast<const typename T::value_type& >(v);
|
||||
getInstance<T>(instance).at(i) = variant_cast<const typename T::value_type& >(v);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -287,8 +285,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual int count(const Value& instance) const
|
||||
{
|
||||
const T& ctr = variant_cast<const T& >(instance);
|
||||
return static_cast<int>(ctr.size());
|
||||
return static_cast<int>(getInstance<T>(instance).size());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -296,8 +293,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual void add(Value& instance, const Value& v) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
ctr.push_back(variant_cast<const typename T::value_type& >(v));
|
||||
getInstance<T>(instance).push_back(variant_cast<const typename T::value_type& >(v));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -305,7 +301,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual void remove(Value& instance, int i) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
T& ctr = getInstance<T>(instance);
|
||||
typename T::iterator j=ctr.begin();
|
||||
std::advance(j, i);
|
||||
ctr.erase(j);
|
||||
@@ -344,7 +340,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual Value get(Value& instance, int i) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
T& ctr = getInstance<T>(instance);
|
||||
typename T::iterator j=ctr.begin();
|
||||
std::advance(j, i);
|
||||
return *j;
|
||||
@@ -352,7 +348,7 @@ namespace osgIntrospection
|
||||
|
||||
virtual Value get(const Value& instance, int i) const
|
||||
{
|
||||
const T& ctr = variant_cast<const T& >(instance);
|
||||
const T& ctr = getInstance<T>(instance);
|
||||
typename T::const_iterator j=ctr.begin();
|
||||
std::advance(j, i);
|
||||
return *j;
|
||||
@@ -363,8 +359,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual int count(const Value& instance) const
|
||||
{
|
||||
const T& ctr = variant_cast<const T& >(instance);
|
||||
return static_cast<int>(ctr.size());
|
||||
return static_cast<int>(getInstance<T>(instance).size());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -372,8 +367,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual void add(Value& instance, const Value& v) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
ctr.insert(variant_cast<const typename T::value_type& >(v));
|
||||
getInstance<T>(instance).insert(variant_cast<const typename T::value_type& >(v));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -381,7 +375,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual void remove(Value& instance, int i) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
T& ctr = getInstance<T>(instance);
|
||||
typename T::iterator j=ctr.begin();
|
||||
std::advance(j, i);
|
||||
ctr.erase(j);
|
||||
@@ -419,7 +413,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual Value get(Value& instance, int i) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
T& ctr = getInstance<T>(instance);
|
||||
typename T::iterator j=ctr.begin();
|
||||
std::advance(j, i);
|
||||
return *j;
|
||||
@@ -427,7 +421,7 @@ namespace osgIntrospection
|
||||
|
||||
virtual Value get(const Value& instance, int i) const
|
||||
{
|
||||
const T& ctr = variant_cast<const T& >(instance);
|
||||
const T& ctr = getInstance<T>(instance);
|
||||
typename T::const_iterator j=ctr.begin();
|
||||
std::advance(j, i);
|
||||
return *j;
|
||||
@@ -438,7 +432,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual void set(Value& instance, int i, const Value& v) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
T& ctr = getInstance<T>(instance);
|
||||
typename T::iterator j=ctr.begin();
|
||||
std::advance(j, i);
|
||||
*j = variant_cast<const typename T::value_type& >(v);
|
||||
@@ -449,8 +443,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual int count(const Value& instance) const
|
||||
{
|
||||
const T& ctr = variant_cast<const T& >(instance);
|
||||
return static_cast<int>(ctr.size());
|
||||
return static_cast<int>(getInstance<T>(instance).size());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -458,8 +451,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual void add(Value& instance, const Value& v) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
ctr.push_back(variant_cast<const typename T::value_type& >(v));
|
||||
getInstance<T>(instance).push_back(variant_cast<const typename T::value_type& >(v));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -467,7 +459,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual void remove(Value& instance, int i) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
T& ctr = getInstance<T>(instance);
|
||||
typename T::iterator j=ctr.begin();
|
||||
std::advance(j, i);
|
||||
ctr.erase(j);
|
||||
@@ -511,7 +503,7 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual Value get(Value& instance, const ValueList& indices) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
T& ctr = getInstance<T>(instance);
|
||||
const key_type& key = variant_cast<const key_type& >(indices.front());
|
||||
|
||||
iterator i = ctr.find(key);
|
||||
@@ -521,7 +513,7 @@ namespace osgIntrospection
|
||||
|
||||
virtual Value get(const Value& instance, const ValueList& indices) const
|
||||
{
|
||||
const T& ctr = variant_cast<const T& >(instance);
|
||||
const T& ctr = getInstance<T>(instance);
|
||||
const key_type& key = variant_cast<const key_type& >(indices.front());
|
||||
|
||||
const_iterator i = ctr.find(key);
|
||||
@@ -534,8 +526,8 @@ namespace osgIntrospection
|
||||
{
|
||||
virtual void set(Value& instance, const ValueList& indices, const Value& v) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
ctr.insert(std::make_pair(variant_cast<const key_type& >(indices.front()), variant_cast<const mapped_type& >(v)));
|
||||
getInstance<T>(instance).insert(std::make_pair(variant_cast<const key_type& >(indices.front()),
|
||||
variant_cast<const mapped_type& >(v)));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -562,7 +554,7 @@ namespace osgIntrospection
|
||||
|
||||
virtual void getIndexValueSet(int /*whichindex*/, const Value& instance, ValueList& values) const
|
||||
{
|
||||
const T& ctr = variant_cast<const T& >(instance);
|
||||
const T& ctr = getInstance<T>(instance);
|
||||
for (const_iterator i=ctr.begin();
|
||||
i!=ctr.end();
|
||||
++i)
|
||||
@@ -604,8 +596,8 @@ namespace osgIntrospection
|
||||
{
|
||||
switch (_i)
|
||||
{
|
||||
case 0: return variant_cast<T& >(instance).first;
|
||||
case 1: return variant_cast<T& >(instance).second;
|
||||
case 0: return getInstance<T>(instance).first;
|
||||
case 1: return getInstance<T>(instance).second;
|
||||
default: return Value();
|
||||
}
|
||||
}
|
||||
@@ -614,15 +606,15 @@ namespace osgIntrospection
|
||||
{
|
||||
switch (_i)
|
||||
{
|
||||
case 0: return variant_cast<const T& >(instance).first;
|
||||
case 1: return variant_cast<const T& >(instance).second;
|
||||
case 0: return getInstance<T>(instance).first;
|
||||
case 1: return getInstance<T>(instance).second;
|
||||
default: return Value();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void set(const Value& instance, const Value& v) const
|
||||
virtual void set(Value& instance, const Value& v) const
|
||||
{
|
||||
T& ctr = variant_cast<T& >(instance);
|
||||
T& ctr = getInstance<T>(instance);
|
||||
|
||||
switch (_i)
|
||||
{
|
||||
|
||||
@@ -46,6 +46,18 @@ namespace osgIntrospection
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> const T &getInstance(const Value &instance)
|
||||
{
|
||||
return instance.isTypedPointer() ?
|
||||
*variant_cast<const T*>(instance) : variant_cast<const T&>(instance);
|
||||
}
|
||||
|
||||
template<typename T> T &getInstance(Value &instance)
|
||||
{
|
||||
return instance.isTypedPointer() ?
|
||||
*variant_cast<T*>(instance) : variant_cast<T&>(instance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user