cpp_load_test.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // Copyright 2016 Klemens Morgenstern
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. // For more information, see http://www.boost.org
  7. #include <boost/predef.h>
  8. #if (__cplusplus >= 201402L) || (BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(14,0,0))
  9. #include "../example/b2_workarounds.hpp"
  10. #include <boost/dll/smart_library.hpp>
  11. #include <boost/core/lightweight_test.hpp>
  12. #include <boost/filesystem.hpp>
  13. #include <boost/variant.hpp>
  14. #include <iostream>
  15. struct override_class
  16. {
  17. int arr[32];
  18. };
  19. int main(int argc, char* argv[])
  20. {
  21. using namespace boost::dll;
  22. using namespace boost::dll::experimental;
  23. boost::dll::fs::path pt = b2_workarounds::first_lib_from_argv(argc, argv);
  24. BOOST_TEST(!pt.empty());
  25. std::cout << "Library: " << pt << std::endl;
  26. std::cerr << 1 << ' ';
  27. smart_library sm(pt);
  28. auto& unscoped_var = sm.get_variable<int>("unscoped_var");
  29. BOOST_TEST(unscoped_var == 42);
  30. std::cerr << 2 << ' ';
  31. auto& unscoped_c_var = sm.get_variable<const double>("unscoped_c_var");
  32. BOOST_TEST(unscoped_c_var == 1.234);
  33. std::cerr << 3 << ' ';
  34. auto& sp_variable = sm.get_variable<double>("some_space::variable");
  35. BOOST_TEST(sp_variable == 0.2);
  36. std::cerr << 4 << ' ';
  37. auto scoped_fun = sm.get_function<const int&()>("some_space::scoped_fun");
  38. BOOST_TEST(scoped_fun != nullptr);
  39. { std::cerr << 5 << ' ';
  40. auto &res = scoped_fun();
  41. const int expected = 0xDEADBEEF;
  42. BOOST_TEST(res == expected);
  43. }
  44. std::cerr << 6 << ' ';
  45. auto ovl1 = sm.get_function<void(int)> ("overloaded");
  46. auto ovl2 = sm.get_function<void(double)>("overloaded");
  47. std::cerr << 7 << ' ';
  48. BOOST_TEST(ovl1 != nullptr);
  49. BOOST_TEST(ovl2 != nullptr);
  50. BOOST_TEST(reinterpret_cast<void*>(ovl1) != reinterpret_cast<void*>(ovl2));
  51. std::cerr << 8 << ' ';
  52. ovl1(12);
  53. BOOST_TEST(unscoped_var == 12);
  54. ovl2(5.0);
  55. BOOST_TEST(sp_variable == 5.0);
  56. std::cerr << 9 << ' ';
  57. auto var1 = sm.get_function<void(boost::variant<int, double> &)>("use_variant");
  58. auto var2 = sm.get_function<void(boost::variant<double, int> &)>("use_variant");
  59. std::cerr << 10 << ' ';
  60. BOOST_TEST(var1 != nullptr);
  61. BOOST_TEST(var2 != nullptr);
  62. BOOST_TEST(reinterpret_cast<void*>(var1) != reinterpret_cast<void*>(var2));
  63. {
  64. boost::variant<int, double> v1 = 232.22;
  65. boost::variant<double, int> v2 = -1;
  66. std::cerr << 11 << ' ';
  67. var1(v1);
  68. var2(v2);
  69. struct : boost::static_visitor<void>
  70. {
  71. void operator()(double) {BOOST_TEST(false);}
  72. void operator()(int i) {BOOST_TEST(i == 42);}
  73. } vis1;
  74. struct : boost::static_visitor<void>
  75. {
  76. void operator()(double d) {BOOST_TEST(d == 3.124);}
  77. void operator()(int ) {BOOST_TEST(false);}
  78. } vis2;
  79. boost::apply_visitor(vis1, v1);
  80. boost::apply_visitor(vis2, v2);
  81. }
  82. std::cerr << 12 << ' ';
  83. /* now test the class stuff */
  84. //first we import and test the global variables
  85. auto& father_val = sm.get_variable<int>("some_space::father_value");
  86. auto& static_val = sm.get_variable<int>("some_space::some_class::value");
  87. BOOST_TEST(father_val == 12);
  88. BOOST_TEST(static_val == -1);
  89. std::cerr << 13 << ' ';
  90. //now get the static function.
  91. auto set_value = sm.get_function<void(const int &)>("some_space::some_class::set_value");
  92. BOOST_TEST(set_value != nullptr);
  93. std::cerr << 14 << ' ';
  94. set_value(42);
  95. BOOST_TEST(static_val == 42); //alright, static method works.
  96. //alright, now import the class members
  97. //first add the type alias.
  98. sm.add_type_alias<override_class>("some_space::some_class");
  99. std::cerr << 15 << ' ';
  100. auto set = sm.get_mem_fn<override_class, void(int)>("set");
  101. std::cerr << 16 << ' ';
  102. try {
  103. sm.get_mem_fn<override_class, int()>("get");
  104. BOOST_TEST(false);
  105. } catch(boost::dll::fs::system_error &) {}
  106. auto get = sm.get_mem_fn<const override_class, int()>("get");
  107. std::cerr << 17 << ' ';
  108. BOOST_TEST(get != nullptr);
  109. BOOST_TEST(set != nullptr);
  110. std::cerr << 18 << ' ';
  111. auto func_dd = sm.get_mem_fn<override_class, double(double, double)>("func");
  112. auto func_ii = sm.get_mem_fn<override_class, int(int, int)> ("func");
  113. auto func_iiv = sm.get_mem_fn<volatile override_class, int(int, int)> ("func");
  114. auto func_ddc = sm.get_mem_fn<const volatile override_class, double(double, double)>("func");
  115. std::cerr << 19 << ' ';
  116. BOOST_TEST(func_dd != nullptr);
  117. BOOST_TEST(func_ii != nullptr);
  118. std::cerr << 20 << ' ';
  119. auto ctor_v = sm.get_constructor<override_class()>();
  120. auto ctor_i = sm.get_constructor<override_class(int)>();
  121. auto dtor = sm.get_destructor<override_class>();
  122. std::cerr << 21 << ' ';
  123. //actually never used.
  124. if (ctor_v.has_allocating())
  125. {
  126. //allocate
  127. auto p = ctor_v.call_allocating();
  128. //assert it works
  129. auto val = (p->*get)();
  130. BOOST_TEST(val == 123);
  131. //deallocate
  132. dtor.call_deleting(p);
  133. //now i cannot assert that it deletes, since it would crash.
  134. }
  135. //More tests to assure the correct this-ptr
  136. std::cerr << 22 << ' ';
  137. typedef override_class * override_class_p;
  138. override_class_p &this_dll = sm.shared_lib().get<override_class_p>("this_");
  139. std::cerr << 23 << ' ';
  140. //ok, now load the ctor/dtor
  141. override_class oc;
  142. override_class_p this_exe = &oc;
  143. for (auto& i : oc.arr) {
  144. i = 0;
  145. }
  146. std::cerr << 24 << ' ';
  147. BOOST_TEST((oc.*get)() == 0); BOOST_TEST(this_dll == this_exe);
  148. ctor_i.call_standard(&oc, 12); BOOST_TEST(this_dll == this_exe);
  149. BOOST_TEST(static_val == 12);
  150. BOOST_TEST((oc.*get)() == 456); BOOST_TEST(this_dll == this_exe);
  151. (oc.*set)(42);
  152. BOOST_TEST((oc.*get)() == 42); BOOST_TEST(this_dll == this_exe);
  153. std::cerr << 25 << ' ';
  154. BOOST_TEST((oc.*func_dd)(3,2) == 6); BOOST_TEST(this_dll == this_exe);
  155. BOOST_TEST((oc.*func_ii)(1,2) == 3); BOOST_TEST(this_dll == this_exe);
  156. BOOST_TEST((oc.*func_ddc)(10,2) == 5); BOOST_TEST(this_dll == this_exe);
  157. BOOST_TEST((oc.*func_iiv)(9,2) == 7); BOOST_TEST(this_dll == this_exe);
  158. std::cerr << 26 << ' ';
  159. dtor.call_standard(&oc); BOOST_TEST(this_dll == this_exe);
  160. BOOST_TEST(static_val == 0);
  161. // TODO: FIX!
  162. #ifndef BOOST_TRAVISCI_BUILD
  163. const auto& ti = sm.get_type_info<override_class>();
  164. BOOST_TEST(ti.name() != nullptr);
  165. #endif
  166. std::cerr << 27 << ' ';
  167. //test the ovls helper.
  168. {
  169. namespace ex = boost::dll::experimental;
  170. auto &var = ex::get<double>(sm, "some_space::variable");
  171. BOOST_TEST(&var == &sp_variable);
  172. auto fun = ex::get<void(int)>(sm, "overloaded");
  173. BOOST_TEST(fun == ovl1);
  174. auto func_ii = sm.get_mem_fn<override_class, int(int, int)> ("func");
  175. auto mem_fn = ex::get<override_class, int(int, int)>(sm, "func");
  176. BOOST_TEST(mem_fn == func_ii);
  177. }
  178. std::cerr << 28 << ' ';
  179. return boost::report_errors();
  180. }
  181. #else
  182. int main() {return 0;}
  183. #endif