]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
2 | <html> | |
3 | <!-- | |
4 | (C) Copyright 2002-4 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 | <head> | |
10 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | |
11 | <link rel="stylesheet" type="text/css" href="../../../boost.css"> | |
12 | <link rel="stylesheet" type="text/css" href="style.css"> | |
13 | <title>Serialization - extended_type_info</title> | |
14 | </head> | |
15 | <body link="#0000ff" vlink="#800080"> | |
16 | <table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header"> | |
17 | <tr> | |
18 | <td valign="top" width="300"> | |
19 | <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../boost.png" border="0"></a></h3> | |
20 | </td> | |
21 | <td valign="top"> | |
22 | <h1 align="center">Serialization</h1> | |
23 | <h2 align="center"><code style="white-space: normal">extended_type_info</code></h2> | |
24 | </td> | |
25 | </tr> | |
26 | </table> | |
27 | <hr> | |
28 | <dl class="page-index"> | |
29 | <dt><a href="#motivation">Motivation</a> | |
30 | <dt><a href="#runtime">Runtime Interface</a> | |
31 | <dt><a href="#requirements">Requirements</a> | |
32 | <dt><a href="#models">Models</a> | |
33 | <dt><a href="#example">Example</a> | |
34 | </dl> | |
35 | ||
36 | <h3><a name="motivation">Motivation</a></h3> | |
37 | The serialization library needs a system like | |
38 | <code style="white-space: normal">type_info/typeid()</code> to perform | |
39 | the following functions | |
40 | <ol> | |
41 | <li> | |
42 | given a pointer to a type T discover the true type pointed to. | |
43 | <li> | |
44 | given an "external" key - determine what type of object to create. | |
45 | </ol> | |
46 | <h3>The problem with <code style="white-space: normal">std::type_info</code></h3> | |
47 | <ul> | |
48 | <li> | |
49 | The main function we require - <code style="white-space: normal">std::typeid()</code> | |
50 | is not available in all environments. Support for this function depends upon | |
51 | runtime typing(RTTI) support from the compiler. This may be non-existent | |
52 | or not enabled for reasons such as a percieved inefficiency. | |
53 | <li> | |
54 | <code style="white-space: normal">std::type_info</code> includes a string | |
55 | containing type name. This would seem to satisfy 2) above. | |
56 | But the format of this string is not consistent accross compilers, libraries, | |
57 | and operating systems. This makes it unusable for support of portable archives. | |
58 | <li> | |
59 | Even if the type name string could somehow be made portable, there is no | |
60 | guarantee that class headers would be included in the same namespace accross | |
61 | different applications. In fact, including different headers in different | |
62 | namespaces is an accepted method used to avoid namespace conflicts. | |
63 | Thus the namespace::class_name can't be used as a key. | |
64 | <li> | |
65 | There exists the possibility that different classes use different type id | |
66 | mechanisms. The class header might include this information. If we want to | |
67 | import class headers accross applications, it's convenient that the type id | |
68 | mechanism support inter-operability accross different type id systems. | |
69 | </ul> | |
70 | <h3>Features</h3> | |
71 | <code style="white-space: normal"><a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp"> | |
72 | extended_type_info</a></code> is an implementation | |
73 | of <code style="white-space: normal">std::type_info</code> functionality with the | |
74 | following features: | |
75 | <ul> | |
76 | <li> | |
77 | Builds a set of <a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp"> | |
78 | <code style="white-space: normal">extended_type_info</a></code> records - one for each type | |
79 | serialized. | |
80 | <li> | |
81 | permits association of an arbitrary string key with a type. Often this key would | |
82 | be the class name - but it doesn't have to be. This key is referred to as | |
83 | a GUID - Globally Unique IDentifier. Presumably it should be unique in the universe. | |
84 | Typically this GUID would be in header files and be used to match type accross | |
85 | applications. The macro BOOST_CLASS_EXPORT can be invoked to associate a string | |
86 | key with any known type. We'll refer to these types as "exported types" | |
87 | <li> | |
88 | permits the "mixing" of type info systems. For example, one class might use | |
89 | <code style="white-space: normal">typeid()</code> to find the external identifier | |
90 | of a class while another might not. | |
91 | </ul> | |
92 | ||
93 | Exported types are maintained in a global table so that given a string key, the | |
94 | corresponding type can be found. This facility is used by the serialization library | |
95 | in order to construct types serialized through a base class pointer. | |
96 | ||
97 | <h3><a name="runtime">Runtime Interface</a></h3> | |
98 | <pre><code"> | |
99 | namespace boost { | |
100 | namespace serialization { | |
101 | ||
102 | class extended_type_info | |
103 | { | |
104 | protected: | |
105 | // this class can't be used as is. It's just the | |
106 | // common functionality for all type_info replacement | |
107 | // systems. Hence, make these protected | |
108 | extended_type_info( | |
109 | const unsigned int type_info_key, | |
110 | const char * key | |
111 | ); | |
112 | ~extended_type_info(); | |
113 | void key_register(); | |
114 | void key_unregister(); | |
115 | public: | |
116 | const char * get_key() const; | |
117 | bool operator<(const extended_type_info &rhs) const; | |
118 | bool operator==(const extended_type_info &rhs) const; | |
119 | bool operator!=(const extended_type_info &rhs) const { | |
120 | return !(operator==(rhs)); | |
121 | } | |
122 | // for plugins | |
123 | virtual void * construct(unsigned int count = 0, ...) const; | |
124 | virtual void destroy(void const * const p) const; | |
125 | static const extended_type_info * find(const char *key); | |
126 | }; | |
127 | ||
128 | } // namespace serialization | |
129 | } // namespace boost | |
130 | </code></pre> | |
131 | <p> | |
132 | Generally, there will be one and only one | |
133 | <code style="white-space: normal"><a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp">extended_type_info</a></code> | |
134 | instance created for each type. However, this is enforced only at the executable | |
135 | module level. That is, if a program includes some shared libraries or DLLS, | |
136 | there may be more than one instance of this class correponding to a particular type. | |
137 | For this reason the comparison functions below can't just compare the addresses of | |
138 | this instance but rather must be programmed to compare the actual information | |
139 | the instances contain. | |
140 | <dl> | |
141 | ||
142 | <dt><h4><pre><code> | |
143 | extended_type_info(unsigned int type_info_key, const char *key); | |
144 | </code></pre></h4></dt> | |
145 | <dd> | |
146 | This constructor should be called by all derived classes. | |
147 | The first argument should be the particular implementation. | |
148 | For this default implementation base on typeid(), this is the | |
149 | value 1. Each system must have its own integer. This value | |
150 | is used to permit the inter-operability of different typeinfo | |
151 | systems. | |
152 | <p> | |
153 | The second argument is a const string which is the external | |
154 | name of the type to which this record corresponds. | |
155 | It may sometimes be referred to as a GUID - a <b>G</b>lobal <b>U</b>nique <b>ID</b>entifier. | |
156 | It is passed through archives from one program invocation to | |
157 | another to uniquely identify the types that the archive contains. | |
158 | If the "export" facility is not going to be used, | |
159 | this value may be NULL. | |
160 | </dd> | |
161 | ||
162 | <dt><h4><pre><code> | |
163 | void key_register(); | |
164 | void key_unregister(); | |
165 | </code></pre></h4></dt> | |
166 | <dd> | |
167 | This system maintains a global table which relates | |
168 | external strings to | |
169 | <code style="white-space: normal">extended_type_info</code> records. | |
170 | This table is used when loading pointers to objects serialized | |
171 | through a base class pointer. In this case, the archive | |
172 | contains a string which is looked up in this table to | |
173 | determine which <code style="white-space: normal">extended_type_info</code> | |
174 | to use for creating a new object. | |
175 | <p> | |
176 | These functions are called by constructors and | |
177 | destructors of classes which implement | |
178 | <code style="white-space: normal">extended_type_info</code> | |
179 | to add and remove entries from this table. | |
180 | </dd> | |
181 | ||
182 | <dt><h4><pre><code> | |
183 | const char *get_key() const; | |
184 | </code></pre></h4></dt> | |
185 | <dd> | |
186 | Retrieves the key for <code style="white-space: normal"><a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp">extended_type_info</a></code> | |
187 | instance. If no key has been associated with the instance, then a NULL is returned. | |
188 | </dd> | |
189 | ||
190 | <dt><h4><pre><code> | |
191 | bool operator<(const extended_type_info & rhs) const; | |
192 | bool operator==(const extended_type_info & rhs) const; | |
193 | bool operator!=(const extended_type_info & rhs) const; | |
194 | </code></pre></h4></dt> | |
195 | <dd> | |
196 | These functions are used to compare | |
197 | <a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp"> | |
198 | <code style="white-space: normal"> | |
199 | extended_type_info | |
200 | </code> | |
201 | </a> | |
202 | objects. They impose a strict total ordering on all | |
203 | <code style="white-space: normal">extended_type_info</code> records. | |
204 | </dd> | |
205 | ||
206 | <dt><h4><pre><code> | |
207 | virtual void * construct(unsigned int count = 0, ...) const; | |
208 | </code></pre></h4></dt> | |
209 | <dd> | |
210 | Construct a new instance of the type to which this | |
211 | <a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp"> | |
212 | <code style="white-space: normal"> | |
213 | extended_type_info | |
214 | </code> | |
215 | </a> | |
216 | record corresponds. This function takes a variable list of up to 4 arguments | |
217 | of any type. These arguments are passed to the type's constructor | |
218 | at runtime. In order to use the facility, | |
219 | one must declare a type sequence for the constructor arguments. | |
220 | Arguments for this function must match in number and type | |
221 | with those specified when the type was exported. | |
222 | This function permits one to create instances of | |
223 | any exported type given only the exported <strong>GUID</strong> assigned | |
224 | with BOOST_CLASS_EXPORT. | |
225 | If these types are defined in DLLS or shared libraries loaded at runtime, | |
226 | these constructors can be called until the module is unloaded. | |
227 | Such modules are referred to as <b>plugins</b>. | |
228 | </code> | |
229 | </dd> | |
230 | ||
231 | <dt><h4><pre><code> | |
232 | virtual void destroy(void const * const p) const; | |
233 | </code></pre></h4></dt> | |
234 | <dd> | |
235 | Destroy an instance created by the above constructor. | |
236 | </dd> | |
237 | ||
238 | <dt><h4><pre><code> | |
239 | static const extended_type_info * find(const char *key); | |
240 | </code></pre></h4></dt> | |
241 | <dd> | |
242 | Given a character string key or <strong>GUID</strong>, return the address of a | |
243 | corresponding <code style="white-space: normal"><a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp">extended_type_info</a></code> | |
244 | object. | |
245 | ||
246 | </dl> | |
247 | ||
248 | <h3><a name="requirements">Requirements for an Implementation</a></h3> | |
249 | In order to be used by the serialization library, an implementation of | |
250 | <code style="white-space: normal">extended_type_info</code>, | |
251 | (referred to as ETI here), must be derived from | |
252 | <a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp"> | |
253 | <code style="white-space: normal"> | |
254 | extended_type_info | |
255 | </code> | |
256 | </a> | |
257 | and also implement the following: | |
258 | ||
259 | <dl> | |
260 | ||
261 | <dt><h4><code style="white-space: normal"><pre> | |
262 | template<class ETI> | |
263 | const extended_type_info * | |
264 | ETI::get_derived_extended_type_info(const T & t) const; | |
265 | </pre></code></h4></dt> | |
266 | <dd> | |
267 | Return a pointer to the | |
268 | <code style="white-space: normal">extended_type_info</code> | |
269 | instance that corresponds to | |
270 | the "true type" of the type T. The "true type" is the lowest type in the | |
271 | hierarchy of classes. The type T can always be cast to the "true type" with | |
272 | a static cast. Implementation of this function will vary among type id systems | |
273 | and sometimes will make presumptions about the type T than can be identified | |
274 | with a particular <code style="white-space: normal">extended_type_info</code> implementation. | |
275 | </dd> | |
276 | ||
277 | <dt><h4><code style="white-space: normal"><pre> | |
278 | virtual bool ETI::is_less_than(const extended_type_info &rhs) const; | |
279 | </pre></code></h4></dt> | |
280 | <dd> | |
281 | Compare this instance to another one using the same | |
282 | <code style="white-space: normal">extended_type_info</code> implementation. | |
283 | </dd> | |
284 | ||
285 | <dt><h4><code style="white-space: normal"><pre> | |
286 | virtual bool ETI::is_equal(const extended_type_info &rhs) const; | |
287 | </pre></code></h4></dt> | |
288 | <dd> | |
289 | Compare this instance to another one using the same | |
290 | <code style="white-space: normal">extended_type_info</code> implementation. | |
291 | Return <code style="white-space: normal">true</code> if the types referred | |
292 | to are the same. Otherwise return | |
293 | <code style="white-space: normal">false</code> | |
294 | </dd> | |
295 | ||
296 | <dt><h4><code style="white-space: normal"><pre> | |
297 | const char ETI::get_key() const; | |
298 | </pre></code></h4></dt> | |
299 | <dd> | |
300 | Retrieve the external key (aka GUID) for this class. | |
301 | </dd> | |
302 | ||
303 | <dt><h4><code style="white-space: normal"><pre> | |
304 | virtual void * construct(unsigned int count, ...) const; | |
305 | </pre></code></h4></dt> | |
306 | <dd> | |
307 | Construct an instance of the corresponding type | |
308 | with the include argument list. | |
309 | </dd> | |
310 | ||
311 | <dt><h4><code style="white-space: normal"><pre> | |
312 | virtual void * destroy(void const * const ptr ) const; | |
313 | </pre></code></h4></dt> | |
314 | <dd> | |
315 | Destroy an instance of this type. This calls the | |
316 | proper destructor and recovers allocated memory. | |
317 | </dd> | |
318 | ||
319 | </dl> | |
320 | ||
321 | <h3><a name="models">Models</a></h3> | |
322 | The serialization library includes two distinct | |
323 | <code style="white-space: normal"><a target="extended_type_info.hpp" href="../../../boost/serialization/extended_type_info.hpp">extended_type_info</a></code> | |
324 | implementations. | |
325 | <p> | |
326 | <code style="white-space: normal"><h4><a target="extended_type_info_typeid.hpp" href = "../../../boost/serialization/extended_type_info_typeid.hpp"> | |
327 | extended_type_info_typeid</a></h4></code>is implemented in terms of the standard typeid(). It presumes that RTTI support is enabled | |
328 | by the compiler. | |
329 | <p> | |
330 | <code style="white-space: normal"><h4><a target="extended_type_info_no_rtti.hpp" href="../../../boost/serialization/extended_type_info_no_rtti.hpp"> | |
331 | extended_type_info_no_rtti</a></h4></code> | |
332 | is implemented in a way that doesn't rely on the existence RTTI. | |
333 | Instead, it requires that all polymorphic types be explictly exported. | |
334 | In addition, if the export facility is to be used to serialize types | |
335 | through base class pointers, those types are required to implement | |
336 | a virtual function with the signature: | |
337 | ||
338 | <code><pre> | |
339 | virtual const char * get_key(); | |
340 | </pre></code> | |
341 | which returns a unique string the most derived object this class. | |
342 | This function must be virtual in order to implement the functionality required by | |
343 | <code style="white-space: normal">ETI::get_derived_extended_type_info</code> | |
344 | as described above. | |
345 | ||
346 | <h3><a name="example">Example</a></h3> | |
347 | The test program <code style="white-space: normal"><a target="test_no_rtti" href="../test/test_no_rtti.cpp">test_no_rtti</a></code> | |
348 | implements this function in terms of the <code style="white-space: normal"><a target="extended_type_info_no_rtti.hpp" href="../../../boost/serialization/extended_type_info_no_rtti.hpp"> | |
349 | extended_type_info</a></code> API above to return the export key associated with the class. | |
350 | This requires that non-abstract types be exported. It also demonstrates the | |
351 | inter-operability between two different implementations of | |
352 | <code style="white-space: normal">extended_type_info</code>. | |
353 | ||
354 | <h3><a name="type_requirements">Requirements for Each Type</a></h3> | |
355 | Each type to be managed by the system must be | |
356 | "registered" individually. This is accomplished by instantiating | |
357 | templates. For example, if the type T is to use the type_info system | |
358 | one would include the following code: | |
359 | ||
360 | <code style="white-space: normal"><pre> | |
361 | namespace boost { | |
362 | namespace serialization { | |
363 | template | |
364 | struct extended_type_info_typeid>T>; | |
365 | template | |
366 | struct extended_type_info_typeid>const T>; | |
367 | } // serialization | |
368 | } // boost | |
369 | </pre></code> | |
370 | ||
371 | For those using the serialization library, this step can be skipped | |
372 | as it is done automatically. The serialization library includes | |
373 | the macro: | |
374 | ||
375 | <code style="white-space: normal"><pre> | |
376 | BOOST_CLASS_TYPE_INFO( | |
377 | my_type, | |
378 | extended_type_info_typeid>my_class> | |
379 | ) | |
380 | </pre></code> | |
381 | ||
382 | which is used to specify which <code>extended_type_info</code> system is to | |
383 | be used for a given type. | |
384 | <p> | |
385 | <code>extended_type_info</code> includes a facility for constructing | |
386 | instances of types without knowing what the exact types are. This is done | |
387 | with the function | |
388 | <code> | |
389 | virtual void * extended_type_info::construct(unsigned int count = 0, ...) const; | |
390 | </code> | |
391 | . For example: | |
392 | <br> | |
393 | <code><pre> | |
394 | struct base { | |
395 | ... | |
396 | }; | |
397 | struct derived : public base { | |
398 | ... | |
399 | }; | |
400 | ... | |
401 | extended_type_info *eti = extended_type_info::find("my_class") | |
402 | base * b = eti->construct(...); | |
403 | </pre></code> | |
404 | <br> | |
405 | The <code>construct</code> takes an argument count and up to | |
406 | four parameters of any type. The arguments are passed to the | |
407 | constructor of "my_class". | |
408 | ||
409 | ||
410 | A complete example of this can be found | |
411 | <a target="test_dll_plugin.cpp" href="../test/test_dll_plugin.cpp">here</a> | |
412 | <hr> | |
413 | <p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2005-2009. | |
414 | Distributed under the Boost Software License, Version 1.0. (See | |
415 | accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
416 | </i></p> | |
417 | </body> | |
418 | </html> |