test_dll_plugin.cpp 6.3 KB

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