Boost Serialization with a dynamically loaded shared library
I've been trying to get Boost serialization working for dynamically loaded shared libraries. Here's my basic structure simplified: 1. base.hpp - includes an abstract base class called base 2. derived.hpp - includes a derived class from base. includes base.hpp. 3. derived.cpp - includes code for derived class and for dynamically loading it 4. main.cpp - includes base.hpp but NOT derived.hpp. dynamically loads instantiates a base * which points to a derived object from derived.so Now in main I want to be able to serialize my pointer to the loaded derived class: base *obj = create_func(); //obj now points to a derived object obj->test(); //when test is run it correctly outputs the message from derived.cpp const base *to_serialize = obj; //it seems to want a const pointer in order to serialize std::ofstream ofs("filename"); boost::archive::text_oarchive oa(ofs); oa << (*to_serialize); main.cpp compiles fine, but when it gets to the last line there, the serialize method in base is called, not the one in derived. I read http://www.boost.org/libs/serialization/doc/serialization.html#derivedpointe... http://www.boost.org/libs/serialization/doc/serialization.html#derivedpointe... but it doesn't seem to address this problem (unless I missed something?). I can't use the BOOST_CLASS_EXPORT_GUID(derived, "derived") macro discussed on that page because main does not know what a derived object is (this is the whole point of having this plugin system). Is there any way I can make boost serialization correctly serialize the derived class from the base pointer when the derived object is known only to a dynamically loaded library? Thank you for your help, Jeshua Bratman -- View this message in context: http://www.nabble.com/Boost-Serialization-with-a-dynamically-loaded-shared-l... Sent from the Boost - Users mailing list archive at Nabble.com.
See comments below Jeshua Bratman wrote:
I've been trying to get Boost serialization working for dynamically loaded shared libraries. Here's my basic structure simplified:
1. base.hpp - includes an abstract base class called base 2. derived.hpp - includes a derived class from base. includes base.hpp. 3. derived.cpp - includes code for derived class and for dynamically loading it 4. main.cpp - includes base.hpp but NOT derived.hpp. dynamically loads instantiates a base * which points to a derived object from derived.so
Now in main I want to be able to serialize my pointer to the loaded derived class:
base *obj = create_func(); //obj now points to a derived object obj->test(); //when test is run it correctly outputs the message from derived.cpp
const base *to_serialize = obj; // I would have prefered const base * const to_serialize = obj ; // the above is OK
//it seems to want a const pointer in order to serialize // see rationale section of documentation
std::ofstream ofs("filename"); boost::archive::text_oarchive oa(ofs); // oa << (*to_serialize); // instead of this oa << to_serialize; // you want to serialize the pointer - NOT the // the obect being pointed to. Once you apply *, you lose the // character of the original object and just get the base class part.
I can't use the BOOST_CLASS_EXPORT_GUID(derived, "derived") macro discussed on that page because main does not know what a derived object is (this is the whole point of having this plugin system).
In order to make this link and run correctly as it stands, you'll have to use EXPORT. To make it work as desiired for plugins, include it in the modules which implement the plug - in - not the main and not the base class.
Is there any way I can make boost serialization correctly serialize the derived class from the base pointer when the derived object is known only to a dynamically loaded library?
It can be done - but it requires more than a casual understanding of the way the compiler and works. The really needs a "case study" in the documentation.
Thank you for your help,
You are welcome. Robert Ramey
Jeshua Bratman
First of all, thank you for the quick and helpful reply! I did as you suggested as to serializing the pointer. It does make much more sense that way, and now it throws an useful exception when I try this serialization: terminate called after throwing an instance of 'boost::archive::archive_exception' what(): unregistered class So clearly I need to export the class as you said because the derived class has not been registered. Robert Ramey wrote:
I can't use the BOOST_CLASS_EXPORT_GUID(derived, "derived") macro discussed on that page because main does not know what a derived object is (this is the whole point of having this plugin system).
In order to make this link and run correctly as it stands, you'll have to use EXPORT. To make it work as desiired for plugins, include it in the modules which implement the plug - in - not the main and not the base class.
I tried exporting the derived class in derived.cpp: BOOST_CLASS_EXPORT_GUID(derived,"derived") But then when I compile the shared library I get about 100 compile errors, many similiar to this: error: incomplete type 'boost::serialization::extended_type_info_null<derived>' used in nested name specifier Do you know what this could be about? I'm guessing it is just something simple I'm not thinking about, but I can't seem to get it to export. This seems very similar to someone else's unresolved problem: http://www.nabble.com/-Serialization--Problem-serialization-of-derived-class... http://www.nabble.com/-Serialization--Problem-serialization-of-derived-class... I am using gentoo with gcc (GCC) 4.1.1 (Gentoo 4.1.1-r3), and boost-1.33.1-r1 Jeshua -- View this message in context: http://www.nabble.com/Boost-Serialization-with-a-dynamically-loaded-shared-l... Sent from the Boost - Users mailing list archive at Nabble.com.
Double check that you're using the macro outside any namespace. Double check that the EXPORT is in the same module as the headers Double check - for 1.33 that the archive headers are before the export header. Check test export and compare it with your own code. Robert Ramey Jeshua Bratman wrote:
First of all, thank you for the quick and helpful reply!
I did as you suggested as to serializing the pointer. It does make much more sense that way, and now it throws an useful exception when I try this serialization:
terminate called after throwing an instance of 'boost::archive::archive_exception' what(): unregistered class
So clearly I need to export the class as you said because the derived class has not been registered.
Robert Ramey wrote:
I can't use the BOOST_CLASS_EXPORT_GUID(derived, "derived") macro discussed on that page because main does not know what a derived object is (this is the whole point of having this plugin system).
In order to make this link and run correctly as it stands, you'll have to use EXPORT. To make it work as desiired for plugins, include it in the modules which implement the plug - in - not the main and not the base class.
I tried exporting the derived class in derived.cpp:
BOOST_CLASS_EXPORT_GUID(derived,"derived")
But then when I compile the shared library I get about 100 compile errors, many similiar to this:
error: incomplete type 'boost::serialization::extended_type_info_null<derived>' used in nested name specifier
Do you know what this could be about? I'm guessing it is just something simple I'm not thinking about, but I can't seem to get it to export.
This seems very similar to someone else's unresolved problem: http://www.nabble.com/-Serialization--Problem-serialization-of-derived-class... http://www.nabble.com/-Serialization--Problem-serialization-of-derived-class...
I am using gentoo with gcc (GCC) 4.1.1 (Gentoo 4.1.1-r3), and boost-1.33.1-r1
Jeshua
Robert Ramey wrote:
Double check that you're using the macro outside any namespace.
Double check that the EXPORT is in the same module as the headers
Double check - for 1.33 that the archive headers are before the export header.
hmm. this is all correct in my code. In fact, this trivial piece of code
does not compile:
#include
Check test export and compare it with your own code.
What do you mean by "Check test export"? Thanks for all the time you're putting into helping me, Jeshua _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users -- View this message in context: http://www.nabble.com/Boost-Serialization-with-a-dynamically-loaded-shared-l... Sent from the Boost - Users mailing list archive at Nabble.com.
I compiled this code with the change below. Uncomment one of the serialization functions. I'm suprised this was necessary - I'll look into it. Robert Ramey Jeshua Bratman wrote:
Robert Ramey wrote:
Double check that you're using the macro outside any namespace.
Double check that the EXPORT is in the same module as the headers
Double check - for 1.33 that the archive headers are before the export header.
hmm. this is all correct in my code. In fact, this trivial piece of code does not compile:
#include
#include #include #include //AFTER all archive headers //BASE class base { public: virtual void virt_func() = 0; }; BOOST_IS_ABSTRACT(base);
//DERIVED class derived : public base { public: void virt_func() {} // template<class Archive> // void serialize(Archive& ar, const unsigned int version); }; BOOST_CLASS_EXPORT_GUID(derived,"derived") //no namespaces here
// template<class Archive> // void serialize(Archive &ar, derived & d, const unsigned int version);
//MAIN int main(){return 0;}
Is this code correct? Does it compile for you?
Check test export and compare it with your own code.
What do you mean by "Check test export"?
Thanks for all the time you're putting into helping me,
Jeshua
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Robert Ramey wrote:
I compiled this code with the change below. Uncomment one of the serialization functions.
Hmm. I still couldn't compile it with those changes. Here's the cpp file I
tried to compile:
error.cpp:
#include
Hmm - I just compiled it on a couple of cmpilers here. gcc 34, MSVC 7.1, borland 5.64. I'm using boost 1.34 + improvements in the serializaiton lirbrar so it might not be the same as you. What version of boost are you using? What version of gcc? If its 1.33 or below try using the following header setup:
#include
#include
#include
#include
Robert Ramey Jeshua Bratman wrote:
Robert Ramey wrote:
I compiled this code with the change below. Uncomment one of the serialization functions.
Hmm. I still couldn't compile it with those changes. Here's the cpp file I tried to compile:
error.cpp: #include
#include #include //BASE class base { public: virtual void virt_func() = 0; }; BOOST_IS_ABSTRACT(base);
//DERIVED class derived : public base { public: void virt_func() {} template<class Archive> void serialize(Archive& ar, const unsigned int version); }; #include
BOOST_CLASS_EXPORT_GUID(derived,"derived") //MAIN int main() { return 0; }
And when I try to compile it:
$ g++ error.cpp -lboost_serialization
/usr/include/boost/serialization/export.hpp: In static member function 'static void boost::archive::detail::guid_initializer<T>::export_register(const char*) [with T = derived]': /usr/include/boost/serialization/export.hpp:155: instantiated from 'boost::archive::detail::guid_initializer<T>::guid_initializer(const char*) [with T = derived]' error.cpp:23: instantiated from here /usr/include/boost/serialization/export.hpp:146: error: incomplete type 'boost::serialization::extended_type_info_null<derived>' used in nested name specifier /usr/include/boost/archive/detail/oserializer.hpp: In constructor 'boost::archive::detail::pointer_oserializer
::pointer_oserializer() [with T = derived, Archive = boost::archive::text_oarchive]': /usr/include/boost/archive/detail/oserializer.hpp:198: instantiated from 'const boost::archive::detail::pointer_oserializer boost::archive::detail::pointer_oserializer ::instance' /usr/include/boost/archive/detail/oserializer.hpp:190: instantiated from 'static const boost::archive::detail::pointer_oserializer & boost::archive::detail::pointer_oserializer ::instantiate() [with T = derived, Archive = boost::archive::text_oarchive]' /usr/include/boost/archive/detail/oserializer.hpp:515: instantiated from 'const boost::archive::detail::basic_pointer_oserializer& boost::archive::detail::instantiate_pointer_oserializer(Archive*, T*) [with Archive = boost::archive::text_oarchive, T = derived]' /usr/include/boost/serialization/export.hpp:83: instantiated from 'static void boost::archive::detail::export_impl::archive ::o::invoke() [with Archive = boost::archive::text_oarchive, T = derived]' /usr/include/boost/serialization/export.hpp:105: instantiated from 'static void boost::archive::detail::export_impl::archive ::instantiate() [with Archive = boost::archive::text_oarchive, T = derived]' ... ... ... [Lots more errors]
I got it to compile, see my second reply to your last message. Robert Ramey wrote:
Hmm - I just compiled it on a couple of cmpilers here. gcc 34, MSVC 7.1, borland 5.64.
I'm using boost 1.34 + improvements in the serializaiton lirbrar so it might not be the same as you.
What version of boost are you using? What version of gcc?
If its 1.33 or below try using the following header setup:
#include
#include #include
#include Robert Ramey
Jeshua Bratman wrote:
Robert Ramey wrote:
I compiled this code with the change below. Uncomment one of the serialization functions.
Hmm. I still couldn't compile it with those changes. Here's the cpp file I tried to compile:
error.cpp: #include
#include #include //BASE class base { public: virtual void virt_func() = 0; }; BOOST_IS_ABSTRACT(base);
//DERIVED class derived : public base { public: void virt_func() {} template<class Archive> void serialize(Archive& ar, const unsigned int version); }; #include
BOOST_CLASS_EXPORT_GUID(derived,"derived") //MAIN int main() { return 0; }
And when I try to compile it:
$ g++ error.cpp -lboost_serialization
/usr/include/boost/serialization/export.hpp: In static member function 'static void boost::archive::detail::guid_initializer<T>::export_register(const char*) [with T = derived]': /usr/include/boost/serialization/export.hpp:155: instantiated from 'boost::archive::detail::guid_initializer<T>::guid_initializer(const char*) [with T = derived]' error.cpp:23: instantiated from here /usr/include/boost/serialization/export.hpp:146: error: incomplete type 'boost::serialization::extended_type_info_null<derived>' used in nested name specifier /usr/include/boost/archive/detail/oserializer.hpp: In constructor 'boost::archive::detail::pointer_oserializer
::pointer_oserializer() [with T = derived, Archive = boost::archive::text_oarchive]': /usr/include/boost/archive/detail/oserializer.hpp:198: instantiated from 'const boost::archive::detail::pointer_oserializer boost::archive::detail::pointer_oserializer ::instance' /usr/include/boost/archive/detail/oserializer.hpp:190: instantiated from 'static const boost::archive::detail::pointer_oserializer & boost::archive::detail::pointer_oserializer ::instantiate() [with T = derived, Archive = boost::archive::text_oarchive]' /usr/include/boost/archive/detail/oserializer.hpp:515: instantiated from 'const boost::archive::detail::basic_pointer_oserializer& boost::archive::detail::instantiate_pointer_oserializer(Archive*, T*) [with Archive = boost::archive::text_oarchive, T = derived]' /usr/include/boost/serialization/export.hpp:83: instantiated from 'static void boost::archive::detail::export_impl::archive ::o::invoke() [with Archive = boost::archive::text_oarchive, T = derived]' /usr/include/boost/serialization/export.hpp:105: instantiated from 'static void boost::archive::detail::export_impl::archive ::instantiate() [with Archive = boost::archive::text_oarchive, T = derived]' ... ... ... [Lots more errors] _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- View this message in context: http://www.nabble.com/Boost-Serialization-with-a-dynamically-loaded-shared-l... Sent from the Boost - Users mailing list archive at Nabble.com.
Now I'm having some success! So, after taking a look at test_exported.cpp I discovered what why the export wouldn't compile. I needed to add a friend declaration: "friend class boost::serialization::access;" to the base and the derived. I fixed that in my shared loader test program and now I no longer get the "unregistered class" exception when I attempt to serialize the pointer to the derived object. However I now get an "unregistered void cast" exception. I'll take a look around the mailing list to see what this is about. Jeshua Bratman -- View this message in context: http://www.nabble.com/Boost-Serialization-with-a-dynamically-loaded-shared-l... Sent from the Boost - Users mailing list archive at Nabble.com.
Jeshua Bratman wrote:
Robert Ramey wrote:
Check test export and compare it with your own code.
What do you mean by "Check test export"?
boost/libs/serialization/test/test_exported.cpp in the boost souce tree I would guess. -- Bjørn
Bjørn Roald wrote:
boost/libs/serialization/test/test_exported.cpp
in the boost souce tree I would guess.
Thank you! Looking at that example file helped alot. -- View this message in context: http://www.nabble.com/Boost-Serialization-with-a-dynamically-loaded-shared-l... Sent from the Boost - Users mailing list archive at Nabble.com.
participants (3)
-
Bjørn Roald
-
Jeshua Bratman
-
Robert Ramey