123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
- // test_dll_plugin.cpp
- // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
- // Use, modification and distribution is subject to the Boost Software
- // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- // should pass compilation and execution
- // Note this test creates, serializes, and destroys
- // a class instance while knowing nothing more than its
- // exported class ID (GUID) and a base class from which
- // it is derived. This is referred to as a "plugin"
- // since the same program could, without recompilation,
- // manipulate any number of derived types - even those
- // which have not been yet been created.
- #include <fstream>
- #include <cstdio> // remove
- #include <boost/config.hpp>
- #if defined(BOOST_NO_STDC_NAMESPACE)
- namespace std{
- using ::remove;
- }
- #endif
- #include <boost/archive/archive_exception.hpp>
- // for now, only test with simple text and polymorphic archive
- #include "test_tools.hpp"
- #include <boost/serialization/base_object.hpp>
- #include <boost/serialization/export.hpp>
- #include <boost/serialization/type_info_implementation.hpp>
- #include <boost/serialization/access.hpp>
- #include <boost/serialization/void_cast.hpp>
- #include <boost/serialization/extended_type_info.hpp>
- #include "polymorphic_base.hpp"
- // declare and implement a derived class in our own executable
- class polymorphic_derived1 : public polymorphic_base
- {
- friend class boost::serialization::access;
- template<class Archive>
- void serialize(Archive &ar, const unsigned int /* file_version */){
- ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(polymorphic_base);
- }
- const char * get_key() const{
- return
- boost::serialization::type_info_implementation<
- polymorphic_derived1
- >::type::get_const_instance().get_key();
- }
- public:
- virtual ~polymorphic_derived1(){}
- };
- // This class is derived from polymorphic_base which uses the no_rtti system
- // rather than the typeid system. This system uses the exported name as the
- // type identifier key. This MUST be exported!!!
- BOOST_CLASS_EXPORT(polymorphic_derived1)
- // MWerks users can do this to make their code work
- BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(polymorphic_base, polymorphic_derived1)
- // save exported polymorphic class
- void save_exported(const char *testfile)
- {
- test_ostream os(testfile, TEST_STREAM_FLAGS);
- test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
- polymorphic_base *rb1 = new polymorphic_derived1;
- // get the eti record for the exported type "polymorphic_derived2"
- boost::serialization::extended_type_info const * const d2_eti =
- boost::serialization::extended_type_info::find(
- "polymorphic_derived2"
- );
- assert(NULL != d2_eti);
- // create a new instance of the type referred to by this record.
- // in this example, we happen to know that the class constructor
- // takes no arguments.
- void const * const rd2 = d2_eti->construct();
- assert(NULL != rd2);
- // transform the pointer to a pointer to the base class
- polymorphic_base const * const rb2
- = static_cast<polymorphic_base const *>(
- boost::serialization::void_upcast(
- * d2_eti,
- boost::serialization::type_info_implementation<polymorphic_base>
- ::type::get_const_instance(),
- rd2
- )
- );
- // export will permit correct serialization
- // through a pointer to a base class
- oa << BOOST_SERIALIZATION_NVP(rb1);
- oa << BOOST_SERIALIZATION_NVP(rb2);
- // don't need these any more - don't leak memory
- delete rb1;
- // note delete original handle - not runtime cast one !!!
- //delete rb2;
- d2_eti->destroy(rd2);
- }
- // save exported polymorphic class
- void load_exported(const char *testfile)
- {
- test_istream is(testfile, TEST_STREAM_FLAGS);
- test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
- polymorphic_base *rb1 = NULL;
- polymorphic_base *rb2 = NULL;
- // export will permit correct serialization
- // through a pointer to a base class
- ia >> BOOST_SERIALIZATION_NVP(rb1);
- BOOST_CHECK_MESSAGE(
- boost::serialization::type_info_implementation<polymorphic_derived1>
- ::type::get_const_instance()
- ==
- * boost::serialization::type_info_implementation<polymorphic_base>
- ::type::get_const_instance().get_derived_extended_type_info(*rb1),
- "restored pointer b1 not of correct type"
- );
- ia >> BOOST_SERIALIZATION_NVP(rb2);
- // get the eti record for the exported type "polymorphic_derived2"
- boost::serialization::extended_type_info const * const d2_eti =
- boost::serialization::extended_type_info::find(
- "polymorphic_derived2"
- );
- assert(NULL != d2_eti);
- BOOST_CHECK_MESSAGE(
- * d2_eti
- ==
- * boost::serialization::type_info_implementation<polymorphic_base>
- ::type::get_const_instance().get_derived_extended_type_info(*rb2),
- "restored pointer b2 not of correct type"
- );
- delete rb1;
- delete rb2;
- }
- #ifdef BOOST_WINDOWS
- #define WIN32_LEAN_AND_MEAN
- #include <TCHAR.H>
- #include <windows.h>
- int
- test_main( int /* argc */, char* /* argv */[] )
- {
- const char * testfile = boost::archive::tmpnam(NULL);
- BOOST_REQUIRE(NULL != testfile);
- HINSTANCE hDLL; // Handle to DLL
- hDLL = LoadLibrary(_T("polymorphic_derived2.dll"));
- BOOST_CHECK_MESSAGE(
- (0 != hDLL),
- "Failed to find/load polymorphic_derived2"
- );
- if(0 == hDLL)
- return EXIT_FAILURE;
- save_exported(testfile);
- load_exported(testfile);
- FreeLibrary(hDLL);
- std::remove(testfile);
- return EXIT_SUCCESS;
- }
- #else // presume *nix
- #include <dlfcn.h>
- int
- test_main( int /* argc */, char* /* argv */[] )
- {
- const char * testfile = boost::archive::tmpnam(NULL);
- BOOST_REQUIRE(NULL != testfile);
- void * hDLL; // Handle to DLL
- hDLL = dlopen("polymorphic_derived2.so", RTLD_NOW | RTLD_GLOBAL);
- BOOST_CHECK_MESSAGE((0 != hDLL), "Failed to find/load plugin_polymorphic_derived2" );
- BOOST_CHECK_MESSAGE((0 != hDLL), dlerror() );
- if(0 == hDLL)
- return EXIT_FAILURE;
- save_exported(testfile);
- load_exported(testfile);
- dlclose(hDLL);
- std::remove(testfile);
- return EXIT_SUCCESS;
- }
- #endif
- // EOF
|