1// Copyright 2011-2012 Renato Tegon Forti.
2// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
3// Copyright Antony Polukhin, 2015-2024.
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt
7// or copy at http://www.boost.org/LICENSE_1_0.txt)
8
9// For more information, see http://www.boost.org
10
11#include "../example/b2_workarounds.hpp"
12#include <boost/dll.hpp>
13#include <boost/core/lightweight_test.hpp>
14#include <boost/function.hpp>
15#include <boost/fusion/container.hpp>
16// lib functions
17
18typedef float (lib_version_func)();
19typedef void (say_hello_func) ();
20typedef int (increment) (int);
21
22typedef boost::fusion::vector<std::vector<int>, std::vector<int>, std::vector<int>, const std::vector<int>*, std::vector<int>* > do_share_res_t;
23typedef boost::shared_ptr<do_share_res_t> (do_share_t)(
24 std::vector<int> v1,
25 std::vector<int>& v2,
26 const std::vector<int>& v3,
27 const std::vector<int>* v4,
28 std::vector<int>* v5
29 );
30
31void refcountable_test(boost::dll::fs::path shared_library_path) {
32 using namespace boost::dll;
33 using namespace boost::fusion;
34
35 std::vector<int> v(1000);
36
37 {
38 boost::function<say_hello_func> sz2
39 = import_symbol<say_hello_func>(lib: shared_library_path, name: "say_hello");
40
41 sz2();
42 sz2();
43 sz2();
44 }
45
46
47#if defined(__GNUC__) && __GNUC__ >= 4 && defined(__ELF__)
48 {
49 const int the_answer = import_symbol<int(int)>(lib: shared_library_path, name: "protected_function")(0);
50 BOOST_TEST_EQ(the_answer, 42);
51 }
52#endif
53
54 {
55 boost::function<std::size_t(const std::vector<int>&)> sz
56 = import_alias<std::size_t(const std::vector<int>&)>(lib: shared_library_path, name: "foo_bar");
57 BOOST_TEST(sz(v) == 1000);
58 }
59
60
61 {
62 boost::function<do_share_t> f;
63
64 {
65 boost::function<do_share_t> f2 = import_alias<do_share_t>(lib: shared_library_path, name: "do_share");
66 f = f2;
67 }
68
69 std::vector<int> v1(1, 1), v2(2, 2), v3(3, 3), v4(4, 4), v5(1000, 5);
70 boost::shared_ptr<do_share_res_t> res = f(v1, v2, v3, &v4, &v5);
71
72 BOOST_TEST(at_c<0>(*res).size() == 1); BOOST_TEST(at_c<0>(*res).front() == 1);
73 BOOST_TEST(at_c<1>(*res).size() == 2); BOOST_TEST(at_c<1>(*res).front() == 2);
74 BOOST_TEST(at_c<2>(*res).size() == 3); BOOST_TEST(at_c<2>(*res).front() == 3);
75 BOOST_TEST(at_c<3>(*res)->size() == 4); BOOST_TEST(at_c<3>(*res)->front() == 4);
76 BOOST_TEST(at_c<4>(*res)->size() == 1000); BOOST_TEST(at_c<4>(*res)->front() == 5);
77
78 BOOST_TEST(at_c<3>(*res) == &v4);
79 BOOST_TEST(at_c<4>(*res) == &v5);
80 BOOST_TEST(at_c<1>(*res).back() == 777);
81 BOOST_TEST(v5.back() == 9990);
82 }
83
84 {
85 boost::shared_ptr<int> i = import_symbol<int>(lib: shared_library_path, name: "integer_g");
86 BOOST_TEST(*i == 100);
87
88 boost::shared_ptr<int> i2;
89 i.swap(other&: i2);
90 BOOST_TEST(*i2 == 100);
91 }
92
93 {
94 boost::function<int&()> f = import_alias<int&()>(lib: shared_library_path, name: "ref_returning_function");
95 BOOST_TEST(f() == 0);
96
97 f() = 10;
98 BOOST_TEST(f() == 10);
99
100 boost::function<int&()> f1 = import_alias<int&()>(lib: shared_library_path, name: "ref_returning_function");
101 BOOST_TEST(f1() == 10);
102
103 f1() += 10;
104 BOOST_TEST(f() == 20);
105 }
106
107 {
108 boost::shared_ptr<const int> i = import_symbol<const int>(lib: shared_library_path, name: "const_integer_g");
109 BOOST_TEST(*i == 777);
110
111 boost::shared_ptr<const int> i2 = i;
112 i.reset();
113 BOOST_TEST(*i2 == 777);
114 }
115
116 {
117 boost::shared_ptr<std::string> s = import_alias<std::string>(lib: shared_library_path, name: "info");
118 BOOST_TEST(*s == "I am a std::string from the test_library (Think of me as of 'Hello world'. Long 'Hello world').");
119
120 boost::shared_ptr<std::string> s2;
121 s.swap(other&: s2);
122 BOOST_TEST(*s2 == "I am a std::string from the test_library (Think of me as of 'Hello world'. Long 'Hello world').");
123 }
124}
125
126// exe function
127extern "C" int BOOST_SYMBOL_EXPORT exef() {
128 return 15;
129}
130
131// Unit Tests
132int main(int argc, char* argv[]) {
133 using namespace boost::dll;
134
135 boost::dll::fs::path shared_library_path = b2_workarounds::first_lib_from_argv(argc, argv);
136 BOOST_TEST(shared_library_path.string().find("test_library") != std::string::npos);
137 BOOST_TEST(b2_workarounds::is_shared_library(shared_library_path));
138
139 refcountable_test(shared_library_path);
140
141 shared_library sl(shared_library_path);
142
143 BOOST_TEST(sl.get<int>("integer_g") == 100);
144
145 sl.get<int>(symbol_name: "integer_g") = 10;
146 BOOST_TEST(sl.get<int>("integer_g") == 10);
147 BOOST_TEST(sl.get<int>(std::string("integer_g")) == 10);
148
149 BOOST_TEST(sl.get<say_hello_func>("say_hello"));
150 sl.get<say_hello_func>(symbol_name: "say_hello")();
151
152 float ver = sl.get<lib_version_func>(symbol_name: "lib_version")();
153 BOOST_TEST(ver == 1.0);
154
155 int n = sl.get<increment>(symbol_name: "increment")(1);
156 BOOST_TEST(n == 2);
157
158 BOOST_TEST(sl.get<const int>("const_integer_g") == 777);
159
160 boost::function<int(int)> inc = sl.get<int(int)>(symbol_name: "increment");
161 BOOST_TEST(inc(1) == 2);
162 BOOST_TEST(inc(2) == 3);
163 BOOST_TEST(inc(3) == 4);
164
165 // Checking that symbols are still available, after another load+unload of the library
166 { shared_library sl2(shared_library_path); }
167
168 BOOST_TEST(inc(1) == 2);
169 BOOST_TEST(sl.get<int>("integer_g") == 10);
170
171
172 // Checking aliases
173 boost::function<std::size_t(const std::vector<int>&)> sz
174 = sl.get_alias<std::size_t(const std::vector<int>&)>(alias_name: "foo_bar");
175
176 std::vector<int> v(10);
177 BOOST_TEST(sz(v) == 10);
178 BOOST_TEST(sl.get_alias<std::size_t>("foo_variable") == 42);
179
180
181 sz = sl.get<std::size_t(*)(const std::vector<int>&)>(symbol_name: "foo_bar");
182 BOOST_TEST(sz(v) == 10);
183 BOOST_TEST(*sl.get<std::size_t*>("foo_variable") == 42);
184
185 { // self
186 shared_library sl(program_location());
187 int val = sl.get<int(void)>(symbol_name: "exef")();
188 BOOST_TEST(val == 15);
189 }
190
191 int& reference_to_internal_integer = sl.get<int&>(symbol_name: "reference_to_internal_integer");
192 BOOST_TEST(reference_to_internal_integer == 0xFF0000);
193
194#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
195 int&& rvalue_reference_to_internal_integer = sl.get<int&&>(symbol_name: "rvalue_reference_to_internal_integer");
196 BOOST_TEST(rvalue_reference_to_internal_integer == 0xFF0000);
197#endif
198
199 return boost::report_errors();
200}
201
202

source code of boost/libs/dll/test/shared_library_get_symbol_test.cpp