• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // test_dll_plugin.cpp
3 
4 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
5 // Use, modification and distribution is subject to the Boost Software
6 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 
9 // should pass compilation and execution
10 
11 // Note this test creates, serializes, and destroys
12 // a class instance while knowing nothing more than its
13 // exported class ID (GUID) and a base class from which
14 // it is derived.  This is referred to as a "plugin"
15 // since the same program could, without recompilation,
16 // manipulate any number of derived types - even those
17 // which have not been yet been created.
18 
19 #include <fstream>
20 
21 #include <cstdio> // remove
22 #include <boost/config.hpp>
23 #if defined(BOOST_NO_STDC_NAMESPACE)
24 namespace std{
25     using ::remove;
26 }
27 #endif
28 
29 #include <boost/archive/archive_exception.hpp>
30 
31 // for now, only test with simple text and polymorphic archive
32 #include "test_tools.hpp"
33 
34 #include <boost/serialization/base_object.hpp>
35 #include <boost/serialization/export.hpp>
36 #include <boost/serialization/type_info_implementation.hpp>
37 #include <boost/serialization/access.hpp>
38 #include <boost/serialization/void_cast.hpp>
39 #include <boost/serialization/extended_type_info.hpp>
40 
41 #include "polymorphic_base.hpp"
42 
43 // declare and implement a derived class in our own executable
44 class polymorphic_derived1 : public polymorphic_base
45 {
46     friend class boost::serialization::access;
47     template<class Archive>
serialize(Archive & ar,const unsigned int)48     void serialize(Archive &ar, const unsigned int /* file_version */){
49         ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(polymorphic_base);
50     }
get_key() const51     const char * get_key() const{
52         return
53             boost::serialization::type_info_implementation<
54                 polymorphic_derived1
55             >::type::get_const_instance().get_key();
56     }
57 public:
~polymorphic_derived1()58     virtual ~polymorphic_derived1(){}
59 };
60 
61 // This class is derived from polymorphic_base which uses the no_rtti system
62 // rather than the typeid system.  This system uses the exported name as the
63 // type identifier key.  This MUST be exported!!!
64 BOOST_CLASS_EXPORT(polymorphic_derived1)
65 
66 // MWerks users can do this to make their code work
BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(polymorphic_base,polymorphic_derived1)67 BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(polymorphic_base, polymorphic_derived1)
68 
69 // save exported polymorphic class
70 void save_exported(const char *testfile)
71 {
72     test_ostream os(testfile, TEST_STREAM_FLAGS);
73     test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
74 
75     polymorphic_base *rb1 = new polymorphic_derived1;
76 
77     // get the eti record for the exported type "polymorphic_derived2"
78     boost::serialization::extended_type_info const * const d2_eti =
79         boost::serialization::extended_type_info::find(
80             "polymorphic_derived2"
81         );
82     assert(NULL != d2_eti);
83 
84     // create a new instance of the type referred to by this record.
85     // in this example, we happen to know that the class constructor
86     // takes no arguments.
87     void const * const rd2 = d2_eti->construct();
88     assert(NULL != rd2);
89 
90     // transform the pointer to a pointer to the base class
91     polymorphic_base const * const rb2
92         = static_cast<polymorphic_base const *>(
93             boost::serialization::void_upcast(
94                 * d2_eti,
95                 boost::serialization::type_info_implementation<polymorphic_base>
96                     ::type::get_const_instance(),
97                 rd2
98             )
99         );
100 
101     // export will permit correct serialization
102     // through a pointer to a base class
103     oa << BOOST_SERIALIZATION_NVP(rb1);
104     oa << BOOST_SERIALIZATION_NVP(rb2);
105 
106     // don't need these any more - don't leak memory
107     delete rb1;
108     // note delete original handle - not runtime cast one !!!
109     //delete rb2;
110     d2_eti->destroy(rd2);
111 }
112 
113 // save exported polymorphic class
load_exported(const char * testfile)114 void load_exported(const char *testfile)
115 {
116     test_istream is(testfile, TEST_STREAM_FLAGS);
117     test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
118 
119     polymorphic_base *rb1 = NULL;
120     polymorphic_base *rb2 = NULL;
121 
122     // export will permit correct serialization
123     // through a pointer to a base class
124     ia >> BOOST_SERIALIZATION_NVP(rb1);
125 
126     BOOST_CHECK_MESSAGE(
127         boost::serialization::type_info_implementation<polymorphic_derived1>
128             ::type::get_const_instance()
129         ==
130         * boost::serialization::type_info_implementation<polymorphic_base>
131             ::type::get_const_instance().get_derived_extended_type_info(*rb1),
132         "restored pointer b1 not of correct type"
133     );
134     ia >> BOOST_SERIALIZATION_NVP(rb2);
135 
136     // get the eti record for the exported type "polymorphic_derived2"
137     boost::serialization::extended_type_info const * const d2_eti =
138         boost::serialization::extended_type_info::find(
139             "polymorphic_derived2"
140         );
141     assert(NULL != d2_eti);
142 
143     BOOST_CHECK_MESSAGE(
144         * d2_eti
145         ==
146         * boost::serialization::type_info_implementation<polymorphic_base>
147             ::type::get_const_instance().get_derived_extended_type_info(*rb2),
148         "restored pointer b2 not of correct type"
149     );
150 
151     delete rb1;
152     delete rb2;
153 }
154 
155 #ifdef BOOST_WINDOWS
156 
157 #define WIN32_LEAN_AND_MEAN
158 #include <TCHAR.H>
159 #include <windows.h>
160 
161 int
test_main(int,char * [])162 test_main( int /* argc */, char* /* argv */[] )
163 {
164     const char * testfile = boost::archive::tmpnam(NULL);
165     BOOST_REQUIRE(NULL != testfile);
166 
167     HINSTANCE hDLL;               // Handle to DLL
168     hDLL = LoadLibrary(_T("polymorphic_derived2.dll"));
169     BOOST_CHECK_MESSAGE(
170         (0 != hDLL),
171         "Failed to find/load polymorphic_derived2"
172     );
173     if(0 == hDLL)
174         return EXIT_FAILURE;
175 
176     save_exported(testfile);
177     load_exported(testfile);
178     FreeLibrary(hDLL);
179 
180     std::remove(testfile);
181     return EXIT_SUCCESS;
182 }
183 
184 #else // presume *nix
185 
186 #include <dlfcn.h>
187 
188 int
test_main(int,char * [])189 test_main( int /* argc */, char* /* argv */[] )
190 {
191     const char * testfile = boost::archive::tmpnam(NULL);
192     BOOST_REQUIRE(NULL != testfile);
193 
194     void * hDLL;               // Handle to DLL
195     hDLL = dlopen("polymorphic_derived2.so", RTLD_NOW | RTLD_GLOBAL);
196     BOOST_CHECK_MESSAGE((0 != hDLL), "Failed to find/load plugin_polymorphic_derived2" );
197     BOOST_CHECK_MESSAGE((0 != hDLL), dlerror() );
198     if(0 == hDLL)
199         return EXIT_FAILURE;
200 
201     save_exported(testfile);
202     load_exported(testfile);
203     dlclose(hDLL);
204 
205     std::remove(testfile);
206     return EXIT_SUCCESS;
207 }
208 
209 #endif
210 
211 // EOF
212