From Colin McDonald and Robert Osfield, "When a serializer shared library is loaded it registers all of

the wrappers it contains.  The registration creates a prototype
object for all of the wrapped classes.  For some of the higher-level
classes this can be a bit heavy.

I noticed a problem with a model which required a single class from
osgSim.  When osgdb_serializers_osgsim.so was loaded it registered
wrappers and created prototype objects for all of the osgSim classes,
including osgSim::ScalarBar.  The constructor for that class creates
several drawables, and loads arial.ttf using the freetype plugin.  I
don't need that, and don't even ship the font or plugin with my
application, resulting in an unexplained warning message loading
the model.

I've modified the ObjectWrapper class to defer the prototype object
creation until if & when actually required."
This commit is contained in:
Robert Osfield 2013-10-02 13:59:00 +00:00
parent 0ec35d5a5d
commit 69f2fb56b3
3 changed files with 28 additions and 23 deletions

View File

@ -48,16 +48,17 @@ public:
typedef std::vector< BaseSerializer::Type > TypeList; typedef std::vector< BaseSerializer::Type > TypeList;
typedef std::vector< osg::ref_ptr<BaseSerializer> > SerializerList; typedef std::vector< osg::ref_ptr<BaseSerializer> > SerializerList;
typedef std::vector< osg::ref_ptr<FinishedObjectReadCallback> > FinishedObjectReadCallbackList; typedef std::vector< osg::ref_ptr<FinishedObjectReadCallback> > FinishedObjectReadCallbackList;
typedef osg::Object* CreateInstanceFunc();
ObjectWrapper( osg::Object* proto, const std::string& name, ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& name,
const std::string& associates ); const std::string& associates );
ObjectWrapper( osg::Object* proto, const std::string& domain, const std::string& name, ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& domain, const std::string& name,
const std::string& associates ); const std::string& associates );
void setUpdatedVersion( int ver ) { _version = ver; } void setUpdatedVersion( int ver ) { _version = ver; }
int getUpdatedVersion() const { return _version; } int getUpdatedVersion() const { return _version; }
const osg::Object* getProto() const { return _proto.get(); } osg::Object* createInstance() const { return _createInstanceFunc(); }
const std::string& getDomain() const { return _domain; } const std::string& getDomain() const { return _domain; }
const std::string& getName() const { return _name; } const std::string& getName() const { return _name; }
const StringList& getAssociates() const { return _associates; } const StringList& getAssociates() const { return _associates; }
@ -87,7 +88,7 @@ protected:
ObjectWrapper() : _version(0) {} ObjectWrapper() : _version(0) {}
virtual ~ObjectWrapper() {} virtual ~ObjectWrapper() {}
osg::ref_ptr<osg::Object> _proto; CreateInstanceFunc* _createInstanceFunc;
std::string _domain; std::string _domain;
std::string _name; std::string _name;
StringList _associates; StringList _associates;
@ -172,7 +173,7 @@ class OSGDB_EXPORT RegisterWrapperProxy
public: public:
typedef void (*AddPropFunc)( ObjectWrapper* ); typedef void (*AddPropFunc)( ObjectWrapper* );
RegisterWrapperProxy( osg::Object* proto, const std::string& name, RegisterWrapperProxy( ObjectWrapper::CreateInstanceFunc *createInstanceFunc, const std::string& name,
const std::string& associates, AddPropFunc func ); const std::string& associates, AddPropFunc func );
virtual ~RegisterWrapperProxy(); virtual ~RegisterWrapperProxy();
@ -186,7 +187,7 @@ class OSGDB_EXPORT RegisterCustomWrapperProxy
public: public:
typedef void (*AddPropFunc)( const char*, ObjectWrapper* ); typedef void (*AddPropFunc)( const char*, ObjectWrapper* );
RegisterCustomWrapperProxy( osg::Object* proto, const std::string& domain, const std::string& name, RegisterCustomWrapperProxy( ObjectWrapper::CreateInstanceFunc *createInstanceFunc, const std::string& domain, const std::string& name,
const std::string& associates, AddPropFunc func ); const std::string& associates, AddPropFunc func );
virtual ~RegisterCustomWrapperProxy(); virtual ~RegisterCustomWrapperProxy();
@ -195,35 +196,39 @@ protected:
osg::ref_ptr<ObjectWrapper> _wrapper; osg::ref_ptr<ObjectWrapper> _wrapper;
}; };
#define REGISTER_OBJECT_WRAPPER(NAME, PROTO, CLASS, ASSOCIATES) \ #define REGISTER_OBJECT_WRAPPER(NAME, CREATEINSTANCE, CLASS, ASSOCIATES) \
extern "C" void wrapper_serializer_##NAME(void) {} \ extern "C" void wrapper_serializer_##NAME(void) {} \
extern void wrapper_propfunc_##NAME(osgDB::ObjectWrapper*); \ extern void wrapper_propfunc_##NAME(osgDB::ObjectWrapper*); \
static osg::Object* wrapper_createinstancefunc##NAME() { return CREATEINSTANCE; } \
static osgDB::RegisterWrapperProxy wrapper_proxy_##NAME( \ static osgDB::RegisterWrapperProxy wrapper_proxy_##NAME( \
PROTO, #CLASS, ASSOCIATES, &wrapper_propfunc_##NAME); \ wrapper_createinstancefunc##NAME, #CLASS, ASSOCIATES, &wrapper_propfunc_##NAME); \
typedef CLASS MyClass; \ typedef CLASS MyClass; \
void wrapper_propfunc_##NAME(osgDB::ObjectWrapper* wrapper) void wrapper_propfunc_##NAME(osgDB::ObjectWrapper* wrapper)
#define REGISTER_OBJECT_WRAPPER2(NAME, PROTO, CLASS, CLASSNAME, ASSOCIATES) \ #define REGISTER_OBJECT_WRAPPER2(NAME, CREATEINSTANCE, CLASS, CLASSNAME, ASSOCIATES) \
extern "C" void wrapper_serializer_##NAME(void) {} \ extern "C" void wrapper_serializer_##NAME(void) {} \
extern void wrapper_propfunc_##NAME(osgDB::ObjectWrapper*); \ extern void wrapper_propfunc_##NAME(osgDB::ObjectWrapper*); \
static osg::Object* wrapper_createinstancefunc##NAME() { return CREATEINSTANCE; } \
static osgDB::RegisterWrapperProxy wrapper_proxy_##NAME( \ static osgDB::RegisterWrapperProxy wrapper_proxy_##NAME( \
PROTO, CLASSNAME, ASSOCIATES, &wrapper_propfunc_##NAME); \ wrapper_createinstancefunc##NAME, CLASSNAME, ASSOCIATES, &wrapper_propfunc_##NAME); \
typedef CLASS MyClass; \ typedef CLASS MyClass; \
void wrapper_propfunc_##NAME(osgDB::ObjectWrapper* wrapper) void wrapper_propfunc_##NAME(osgDB::ObjectWrapper* wrapper)
#define REGISTER_CUSTOM_OBJECT_WRAPPER(DOMAIN, NAME, PROTO, CLASS, ASSOCIATES) \ #define REGISTER_CUSTOM_OBJECT_WRAPPER(DOMAIN, NAME, CREATEINSTANCE, CLASS, ASSOCIATES) \
extern "C" void wrapper_serializer_##NAME(void) {} \ extern "C" void wrapper_serializer_##NAME(void) {} \
extern void wrapper_propfunc_##NAME(const char*, osgDB::ObjectWrapper*); \ extern void wrapper_propfunc_##NAME(const char*, osgDB::ObjectWrapper*); \
static osg::Object* wrapper_createinstancefunc##NAME() { return CREATEINSTANCE; } \
static osgDB::RegisterCustomWrapperProxy wrapper_proxy_##NAME( \ static osgDB::RegisterCustomWrapperProxy wrapper_proxy_##NAME( \
PROTO, #DOMAIN, #CLASS, ASSOCIATES, &wrapper_propfunc_##NAME); \ wrapper_createinstancefunc##NAME, #DOMAIN, #CLASS, ASSOCIATES, &wrapper_propfunc_##NAME); \
typedef CLASS MyClass; \ typedef CLASS MyClass; \
void wrapper_propfunc_##NAME(const char* domain, osgDB::ObjectWrapper* wrapper) void wrapper_propfunc_##NAME(const char* domain, osgDB::ObjectWrapper* wrapper)
#define REGISTER_CUSTOM_OBJECT_WRAPPER2(DOMAIN, NAME, PROTO, CLASS, CLASSNAME, ASSOCIATES) \ #define REGISTER_CUSTOM_OBJECT_WRAPPER2(DOMAIN, NAME, CREATEINSTANCE, CLASS, CLASSNAME, ASSOCIATES) \
extern "C" void wrapper_serializer_##NAME(void) {} \ extern "C" void wrapper_serializer_##NAME(void) {} \
extern void wrapper_propfunc_##NAME(const char*, osgDB::ObjectWrapper*); \ extern void wrapper_propfunc_##NAME(const char*, osgDB::ObjectWrapper*); \
static osg::Object* wrapper_createinstancefunc##NAME() { return CREATEINSTANCE; } \
static osgDB::RegisterCustomWrapperProxy wrapper_proxy_##NAME( \ static osgDB::RegisterCustomWrapperProxy wrapper_proxy_##NAME( \
PROTO, #DOMAIN, CLASSNAME, ASSOCIATES, &wrapper_propfunc_##NAME); \ wrapper_createinstancefunc##NAME, #DOMAIN, CLASSNAME, ASSOCIATES, &wrapper_propfunc_##NAME); \
typedef CLASS MyClass; \ typedef CLASS MyClass; \
void wrapper_propfunc_##NAME(const char* domain, osgDB::ObjectWrapper* wrapper) void wrapper_propfunc_##NAME(const char* domain, osgDB::ObjectWrapper* wrapper)

View File

@ -792,7 +792,7 @@ osg::Object* InputStream::readObjectFields( const std::string& className, unsign
return NULL; return NULL;
} }
osg::ref_ptr<osg::Object> obj = existingObj ? existingObj : wrapper->getProto()->cloneType(); osg::ref_ptr<osg::Object> obj = existingObj ? existingObj : wrapper->createInstance();
_identifierMap[id] = obj; _identifierMap[id] = obj;
if ( obj.valid() ) if ( obj.valid() )
{ {

View File

@ -84,18 +84,18 @@ void osgDB::split( const std::string& src, StringList& list, char separator )
// //
// ObjectWrapper // ObjectWrapper
// //
ObjectWrapper::ObjectWrapper( osg::Object* proto, const std::string& name, ObjectWrapper::ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& name,
const std::string& associates ) const std::string& associates )
: osg::Referenced(), : osg::Referenced(),
_proto(proto), _name(name), _version(0) _createInstanceFunc(createInstanceFunc), _name(name), _version(0)
{ {
split( associates, _associates ); split( associates, _associates );
} }
ObjectWrapper::ObjectWrapper( osg::Object* proto, const std::string& domain, const std::string& name, ObjectWrapper::ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& domain, const std::string& name,
const std::string& associates ) const std::string& associates )
: osg::Referenced(), : osg::Referenced(),
_proto(proto), _domain(domain), _name(name), _version(0) _createInstanceFunc(createInstanceFunc), _domain(domain), _name(name), _version(0)
{ {
split( associates, _associates ); split( associates, _associates );
} }
@ -312,10 +312,10 @@ void ObjectWrapper::writeSchema( StringList& properties, TypeList& types )
// //
// RegisterWrapperProxy // RegisterWrapperProxy
// //
RegisterWrapperProxy::RegisterWrapperProxy( osg::Object* proto, const std::string& name, RegisterWrapperProxy::RegisterWrapperProxy( ObjectWrapper::CreateInstanceFunc *createInstanceFunc, const std::string& name,
const std::string& associates, AddPropFunc func ) const std::string& associates, AddPropFunc func )
{ {
_wrapper = new ObjectWrapper( proto, name, associates ); _wrapper = new ObjectWrapper( createInstanceFunc, name, associates );
if ( func ) (*func)( _wrapper.get() ); if ( func ) (*func)( _wrapper.get() );
if (Registry::instance()) if (Registry::instance())
@ -337,10 +337,10 @@ RegisterWrapperProxy::~RegisterWrapperProxy()
// RegisterCustomWrapperProxy // RegisterCustomWrapperProxy
// //
RegisterCustomWrapperProxy::RegisterCustomWrapperProxy( RegisterCustomWrapperProxy::RegisterCustomWrapperProxy(
osg::Object* proto, const std::string& domain, const std::string& name, ObjectWrapper::CreateInstanceFunc *createInstanceFunc, const std::string& domain, const std::string& name,
const std::string& associates, AddPropFunc func ) const std::string& associates, AddPropFunc func )
{ {
_wrapper = new ObjectWrapper( proto, domain, name, associates ); _wrapper = new ObjectWrapper( createInstanceFunc, domain, name, associates );
if ( func ) (*func)( domain.c_str(), _wrapper.get() ); if ( func ) (*func)( domain.c_str(), _wrapper.get() );
if (Registry::instance()) if (Registry::instance())