[Serialization] Unregistered_class exception

Hello And I am sorry for bothering again The last couple of weeks I am trying to implement saving projects future in my program with boost serialization. However it seems that it is more hard that I think :) Now I am getting unregistered_class exception all over the place First some info about what I am trying to do : I am developing a plugin dll , which is loaded in third party main program. My plugin , say MyPlugin.dll , contains serialization code ( non intrusive save/load pair ) for classes which are defined in third party dll , say A.dll. A.dll is suppiled with my third party main program. Both A.dll and MyPlugin.dll are laoded at runtime in my main program. Only MyPlugin.dll ( and not A.dll and main program ) links with boost 1.41.0 staticly, if this is relevant at all. And I am using Visual Studio 2005. I think that I am getting this unregistered_class exception because somehow I am getting weird behavior from typeid operator ( maybe some bug), for particular class form A.dll. Note that the class have virtual methods. That is if I say : std::string s1=typeid(ON_Brep).raw_name(); ON_Brep someBrepObj; std:string s2=typeid(someTypeObj).raw_name(); s1 and s2 are not the same string. I am doing the following : /////////////////////MyPlugin.cpp //all archive classes are included here namespace boost { namespace serialization { template<class Archive> inline void save(Archive & ar,const ON_Brep& t,const unsigned int version) { boost::serialization::void_cast_register<ON_Brep, ON_Geometry>( static_cast<ON_Brep*>(NULL), static_cast<ON_Geometry *>(NULL)); //save ON_Brep here } template<class Archive> inline void load(Archive & ar,ON_Brep& t,const unsigned int version) { boost::serialization::void_cast_register<ON_Brep, ON_Geometry>( static_cast<ON_Brep*>(NULL), static_cast<ON_Geometry *>(NULL)); //load ON_Brep here } } } BOOST_SERIALIZATION_SPLIT_FREE(ON_Brep) BOOST_CLASS_EXPORT_GUID(ON_Brep, "ON_Brep") void CommandFunction() { ON_Brep* brep=GetBrepObject(); boost::archive::xml_oarchive oa(ofs); oa & BOOST_SERIALIZATION_NVP(brep); // fails to save with uregistered_class exception } The unregistered_exception is thrown before control gets to my nonintrusive save function for my ON_Brep Actually the exception is thrown in oserializer.hpp in line 376 : const boost::serialization::extended_type_info * true_type = i.get_derived_extended_type_info(t); // here throws if(NULL == true_type){ boost::serialization::throw_exception( archive_exception( archive_exception::unregistered_class, true_type->get_debug_info() ) ); } get_derived_extended_type_info is trying to get the eti record for ON_Brep, but I think that that it gets it wrong, because of the weird typeid behavior. get_derived_extended_type_info(const T & t) const { // note: this implementation - based on usage of typeid (rtti) // only does something if the class has at least one virtual function. BOOST_STATIC_WARNING(boost::is_polymorphic<T>::value); return typeid_system::extended_type_info_typeid_0::get_extended_type_info( typeid(t) ); /////// Here the typeid(t) differs from typeid(ON_Brep) <------------------1 } The thing is when I export ON_Brep with BOOST_CLASS_EXPORT_GUID(ON_Brep,"ON_Brep") extended_type_info entry is inserted in the global map, just typeid(ON_Brep) is inserted in the global map But when control gets to <-----1 the typeid(t) is different than the typeid that is entered in the global map,and just looking in the global map fails, becuase I have different behavior when I apply typeid(ON_Brep).raw_name();//this gives me ".?AVON_Brep@@" ON_Brep someBrepObj; typeid(someBrepObj).raw_name();// this gives me ".?.?AVTL_Brep@@" Anyone have seen such a thing ? Thanks for any help

** This scenario is possible. But it is a little tricky for a number of reasons. I've just updated the test "test_dll_plugin" on the trunk. I think this addresses you're situation. I am developing a plugin dll , which is loaded in third party main program. My plugin , say MyPlugin.dll , contains serialization code ( non intrusive save/load pair ) for classes which are defined in third party dll , say A.dll. A.dll is suppiled with my third party main program. Both A.dll and MyPlugin.dll are laoded at runtime in my main program. Only MyPlugin.dll ( and not A.dll and main program ) links with boost 1.41.0 staticly, if this is relevant at all. And I am using Visual Studio 2005. *** If this were me, I would do the following: a) have a header with an abstract base class with an all inline member functions. That is with no *.cpp file, at least one function virtual ... = 0; call this Base The i would make my derived class - Plugin1 derive from Base What we want to do is to save/load through a pointer to the Base class. The basic problem is that when loading through the base class pointer, a instance the derived class must be created - but which one. This is addressed by the "export" facility. The serialization library uses this facility to add information to the archive indicating the true type which has been saved and to construct a new instance of this type when loading. It also instanciates code otherwise would be ecluded from the final executable since it's not explicitly referred to. First I would do this without going through the DLL process just to make sure everything works. Look at demo_pimpl to see how this is done. This totally separates the derived class definition from the rest of the program. So make sure that demo_pimpl works in your setup and that you understand the motivation for everthing that's in there. If you get this far, you can move on to test_dll_plugin. (note I recently uploaded recent changes to the trunk for this demo). Basically, this test/demo is similar to demo_pimpl except that the code for the definition of the derived2 class is totally implemented inside a dll. The main application only knows about the base class. When the DLL containing the definition of the derived2 class is loaded, the boost "export" facility "registers" the derived2 type in a global table. This information is used by the library to properly save and restore the true type of an object given only a pointer to it's base. Note that my approach guarentees that ALL code related to derived2 is contained in ONE DLL. This makes sense to me from a code management standpoint. It also means that there will be only one entry in the global type table for derived2. The serialization library SHOULD handle the situation when code is spread accross multiple DLLs - but why tempt fate? *** Note that using the statically linked c runtime library in one module while using the dynamically linked c runtime library in another is known to cause difficulties. This is unrelated to serialization. The VC IDE permits one to do this even though it can lead to problems. I would recommend that if you're going to use DLLS, you link everything to the dynamically linked version of the c runtime library. I am doing the following : /////////////////////MyPlugin.cpp //all archive classes are included here namespace boost { namespace serialization { template<class Archive> inline void save(Archive & ar,const ON_Brep& t,const unsigned int version) { boost::serialization::void_cast_register<ON_Brep, ON_Geometry>( static_cast<ON_Brep*>(NULL), static_cast<ON_Geometry *>(NULL)); //save ON_Brep here *** to simplify things I would use BOOST_SERIALIZATION_BASE_OBJECT_NVP(ON_Geometry>(*this) and make sure the base has a "serialize function even if it's null } template<class Archive> inline void load(Archive & ar,ON_Brep& t,const unsigned int version) { boost::serialization::void_cast_register<ON_Brep, ON_Geometry>( static_cast<ON_Brep*>(NULL), static_cast<ON_Geometry *>(NULL)); //load ON_Brep here } } } BOOST_SERIALIZATION_SPLIT_FREE(ON_Brep) BOOST_CLASS_EXPORT_GUID(ON_Brep, "ON_Brep") *** I would put this in a *.cpp file as recommended in the documentation. void CommandFunction() { ON_Brep* brep=GetBrepObject(); boost::archive::xml_oarchive oa(ofs); *** where is ofs declared? oa & BOOST_SERIALIZATION_NVP(brep); // fails to save with uregistered_class exception *** another problem. it looks like ON_Brep is a derived object. I doubt you want this. if have ar << x and later ar >> y then x and y MUST be of the same type. In the case of plugin that type would be a pointer to the BASE class. } get_derived_extended_type_info(const T & t) const { // note: this implementation - based on usage of typeid (rtti) // only does something if the class has at least one virtual function. BOOST_STATIC_WARNING(boost::is_polymorphic<T>::value); return typeid_system::extended_type_info_typeid_0::get_extended_type_info( typeid(t) ); /////// Here the typeid(t) differs from typeid(ON_Brep) <------------------1 } Anyone have seen such a thing ? *** almost daily Thanks for any help *** you're welcome Robert Ramey

I use the news microsoft outlook newsreader with quote fix. Sometimes it works as I expect. Other times - like responding to posts which include html it doesn't do what I expect. Also I get - as I do with just about all windows programs - a lot of "automatic" and "helpful" behavior which often works - except when it doesn't - when it leaves me totally mistified. It's getting worse all the time - I'm feeling stupider all the time. Anyway, I'll try. Robert Ramey Steven Watanabe wrote:
AMDG
Robert Ramey wrote:
<snip>
Robert, would it be possible for you to use more standard quoting? I'm afraid I often have a hard time unraveling which parts of your posts were added by you and which are quoted from earlier messages in the thread.
In Christ, Steven Watanabe

Thank you Robert and Steven for all of your help and guidelines. The problem was due to some undocumented inheritance of that particular class ( and that was the reason about the misbehaved typeid operator ). For now, all of my other classes of the same vendor are working as expected. I let you know if I have more troubles :) On Wed, Dec 23, 2009 at 7:30 PM, Robert Ramey <ramey@rrsd.com> wrote:
I use the news microsoft outlook newsreader with quote fix.
Sometimes it works as I expect.
Other times - like responding to posts which include html it doesn't do what I expect.
Also I get - as I do with just about all windows programs - a lot of "automatic" and "helpful" behavior which often works - except when it doesn't - when it leaves me totally mistified. It's getting worse all the time - I'm feeling stupider all the time.
Anyway, I'll try.
Robert Ramey
Steven Watanabe wrote:
AMDG
Robert Ramey wrote:
<snip>
Robert, would it be possible for you to use more standard quoting? I'm afraid I often have a hard time unraveling which parts of your posts were added by you and which are quoted from earlier messages in the thread.
In Christ, Steven Watanabe
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (3)
-
elizabeta petreska
-
Robert Ramey
-
Steven Watanabe