diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/dll | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/dll')
50 files changed, 4092 insertions, 0 deletions
diff --git a/src/boost/libs/dll/README.md b/src/boost/libs/dll/README.md new file mode 100644 index 000000000..f21db0331 --- /dev/null +++ b/src/boost/libs/dll/README.md @@ -0,0 +1,20 @@ +# [Boost Dynamic Library Load (Boost.DLL)](http://boost.org/libs/dll) + +Boost.DLL is a part of the [Boost C++ Libraries](http://github.com/boostorg). It is a library for comfortable work with DLL and DSO. + +### Test results + +Branches | Build | Tests coverage | More info +----------------|-------------- | -------------- |----------- +Develop: | [![Build Status](https://travis-ci.org/apolukhin/Boost.DLL.svg?branch=develop)](https://travis-ci.org/apolukhin/Boost.DLL) [![Build status](https://ci.appveyor.com/api/projects/status/t6q6yhcabtk5b99l/branch/develop?svg=true)](https://ci.appveyor.com/project/apolukhin/boost-dll/branch/develop) | [![Coverage Status](https://coveralls.io/repos/apolukhin/Boost.DLL/badge.png?branch=develop)](https://coveralls.io/r/apolukhin/Boost.DLL?branch=develop) | [details...](http://www.boost.org/development/tests/develop/developer/dll.html) +Master: | [![Build Status](https://travis-ci.org/apolukhin/Boost.DLL.svg?branch=master)](https://travis-ci.org/apolukhin/Boost.DLL) [![Build status](https://ci.appveyor.com/api/projects/status/t6q6yhcabtk5b99l/branch/master?svg=true)](https://ci.appveyor.com/project/apolukhin/boost-dll/branch/master) | [![Coverage Status](https://coveralls.io/repos/apolukhin/Boost.DLL/badge.png?branch=master)](https://coveralls.io/r/apolukhin/Boost.DLL?branch=master) | [details...](http://www.boost.org/development/tests/master/developer/dll.html) + +[Open Issues](https://svn.boost.org/trac/boost/query?status=!closed&component=dll) + +[Latest developer documentation](http://apolukhin.github.io/Boost.DLL/index.html) + +### About +This library was derived from the [Boost.Application](https://github.com/retf/Boost.Application) library. + +### License +Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). diff --git a/src/boost/libs/dll/example/b2_workarounds.hpp b/src/boost/libs/dll/example/b2_workarounds.hpp new file mode 100644 index 000000000..bb9f8ae56 --- /dev/null +++ b/src/boost/libs/dll/example/b2_workarounds.hpp @@ -0,0 +1,109 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_DLL_EXAMPLE_COMMON_B2_WORKAROUNDS_HPP +#define BOOST_DLL_EXAMPLE_COMMON_B2_WORKAROUNDS_HPP + +#include <boost/dll/config.hpp> +#include <boost/filesystem.hpp> +#include <boost/system/error_code.hpp> +#include <iostream> +#include <cctype> + +namespace b2_workarounds { + + +inline boost::filesystem::path drop_version(const boost::filesystem::path& lhs) { + boost::filesystem::path ext = lhs.filename().extension(); + if (ext.native().size() > 1 && std::isdigit(ext.string()[1])) { + ext = lhs; + ext.replace_extension().replace_extension().replace_extension(); + return ext; + } + + return lhs; +} + +inline bool is_shared_library(const std::string& s) { + return (s.find(".dll") != std::string::npos || s.find(".so") != std::string::npos || s.find(".dylib") != std::string::npos) + && s.find(".lib") == std::string::npos + && s.find(".exp") == std::string::npos + && s.find(".pdb") == std::string::npos + && s.find(".manifest") == std::string::npos + && s.find(".rsp") == std::string::npos + && s.find(".obj") == std::string::npos + && s.find(".a") == std::string::npos; +} + +inline bool is_shared_library(const char* p) { + return b2_workarounds::is_shared_library(std::string(p)); +} + +inline bool is_shared_library(const boost::filesystem::path& p) { + return b2_workarounds::is_shared_library(p.string()); +} + +inline boost::dll::fs::path first_lib_from_argv(int argc, char* argv[]) { + BOOST_ASSERT(argc > 1); + (void)argc; + + for (int i = 1; i < argc; ++i) { + if (b2_workarounds::is_shared_library(argv[i])) { + return argv[i]; + } + + std::cout << "b2_workarounds::first_lib_from_argv(argc, argv): skipping '" << argv[i] << "'" << std::endl; + } + + BOOST_ASSERT(false); + return argv[1]; +} + +// This ugly struct is required to drop library version from shared library generated by b2. +struct argv_to_path_guard { + const boost::filesystem::path original_; + const boost::filesystem::path version_dropped_; + const std::string just_path_; + const bool same_; + + + static inline boost::filesystem::path drop_b2_deco(const boost::filesystem::path& in) { + std::size_t pos = in.filename().string().find("-"); + boost::filesystem::path res = in.parent_path() / in.filename().string().substr(0, in.filename().string().find("-")); + if (pos != std::string::npos) { + res += in.extension(); + } + return res; + } + + inline explicit argv_to_path_guard(int argc, char* argv[]) + : original_(first_lib_from_argv(argc, argv)) + , version_dropped_( drop_b2_deco(drop_version(original_)) ) + , just_path_( version_dropped_.parent_path().string() ) + , same_(version_dropped_ == original_) + { + if (!same_) { + boost::system::error_code ignore; + boost::filesystem::remove(version_dropped_, ignore); + boost::filesystem::copy(original_, version_dropped_, ignore); + } + + argv[1] = const_cast<char*>(just_path_.c_str()); + } + + inline ~argv_to_path_guard() { + if (!same_) { + boost::system::error_code ignore; + boost::filesystem::remove(version_dropped_, ignore); + } + } +}; + +} // namespace b2_workarounds + +#endif // BOOST_DLL_EXAMPLE_COMMON_B2_WORKAROUNDS_HPP + diff --git a/src/boost/libs/dll/example/getting_started.cpp b/src/boost/libs/dll/example/getting_started.cpp new file mode 100644 index 000000000..4d634662a --- /dev/null +++ b/src/boost/libs/dll/example/getting_started.cpp @@ -0,0 +1,83 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/core/lightweight_test.hpp> +#include <boost/dll.hpp> +#include <boost/function.hpp> +#include <string> +#include "b2_workarounds.hpp" + +// Unit Tests +int main(int argc, char* argv[]) { + using namespace boost; + + boost::dll::fs::path path_to_shared_library = b2_workarounds::first_lib_from_argv(argc, argv); + BOOST_TEST(path_to_shared_library.string().find("getting_started_library") != std::string::npos); + + //[getting_started_imports_c_function + // Importing pure C function + function<int(int)> c_func = dll::import<int(int)>( + path_to_shared_library, "c_func_name" + ); + //] + + int c_func_res = c_func(1); // calling the function + BOOST_TEST(c_func_res == 2); + + + //[getting_started_imports_c_variable + // Importing pure C variable + shared_ptr<int> c_var = dll::import<int>( + path_to_shared_library, "c_variable_name" + ); + //] + + int c_var_old_contents = *c_var; // using the variable + *c_var = 100; + BOOST_TEST(c_var_old_contents == 1); + + + //[getting_started_imports_alias + // Importing function by alias name + /*<-*/ function<std::string(const std::string&)> /*->*/ /*=auto*/ cpp_func = dll::import_alias<std::string(const std::string&)>( + path_to_shared_library, "pretty_name" + ); + //] + + // calling the function + std::string cpp_func_res = cpp_func(std::string("In importer.")); + BOOST_TEST(cpp_func_res == "In importer. Hello from lib!"); + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + //[getting_started_imports_cpp11_function + // Importing function. + auto cpp11_func = dll::import<int(std::string&&)>( + path_to_shared_library, "i_am_a_cpp11_function" + ); + //] + + // calling the function + int cpp11_func_res = cpp11_func(std::string("In importer.")); + BOOST_TEST(cpp11_func_res == sizeof("In importer.") - 1); +#endif + + + //[getting_started_imports_cpp_variable + // Importing variable. + shared_ptr<std::string> cpp_var = dll::import<std::string>( + path_to_shared_library, "cpp_variable_name" + ); + //] + + std::string cpp_var_old_contents = *cpp_var; // using the variable + *cpp_var = "New value"; + BOOST_TEST(cpp_var_old_contents == "some value"); + BOOST_TEST(*cpp_var == "New value"); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/dll/example/getting_started_library.cpp b/src/boost/libs/dll/example/getting_started_library.cpp new file mode 100644 index 000000000..0264fd33b --- /dev/null +++ b/src/boost/libs/dll/example/getting_started_library.cpp @@ -0,0 +1,70 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// MinGW related workaround +#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION + +#include <boost/dll.hpp> +#include <string> + +#ifdef BOOST_NO_CXX11_NOEXCEPT +#define noexcept +#endif + +#define API extern "C" BOOST_SYMBOL_EXPORT + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +//[getting_started_exports_cpp11_function +namespace some_namespace { + API int i_am_a_cpp11_function(std::string&& param) noexcept; +// ^-------------------- function name to use in dll::import<> +} +//] +#endif + + +//[getting_started_exports_cpp_variable +namespace your_project_namespace { + API std::string cpp_variable_name; +} +//] + + + +//[getting_started_exports_alias +namespace some_namespace { + std::string i_am_function_with_ugly_name(const std::string& param) noexcept; +} + +// When you have no control over function sources or wish to specify another name. +BOOST_DLL_ALIAS(some_namespace::i_am_function_with_ugly_name, pretty_name) +//] + +//[getting_started_exports_c_function +API int c_func_name(int); +//] + +//[getting_started_exports_c_variable +API int c_variable_name; +//] + +int c_func_name(int i) { return ++i; } +int c_variable_name = 1; +std::string your_project_namespace::cpp_variable_name = "some value"; + +namespace some_namespace { + std::string i_am_function_with_ugly_name(const std::string& param) noexcept { + return param + " Hello from lib!"; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + int i_am_a_cpp11_function(std::string&& param) noexcept { + return static_cast<int>(param.size()); + } +#endif +} + diff --git a/src/boost/libs/dll/example/mangled/import_class.cpp b/src/boost/libs/dll/example/mangled/import_class.cpp new file mode 100644 index 000000000..eee4a9616 --- /dev/null +++ b/src/boost/libs/dll/example/mangled/import_class.cpp @@ -0,0 +1,47 @@ +// Copyright 2016 Klemens Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include "../b2_workarounds.hpp" // contains dll_test::replace_with_full_path + +//[import_class_setup + +#include <boost/dll/smart_library.hpp> +#include <boost/dll/import_mangled.hpp> +#include <boost/dll/import_class.hpp> + + + +int main(int argc, char* argv[]) { + /*<-*/ b2_workarounds::argv_to_path_guard guard(argc, argv); /*->*/ + boost::dll::fs::path lib_path(argv[1]); // argv[1] contains path to directory with our plugin library + smart_library lib(lib_path);// smart library instance +//] +//[import_class_size + auto size_f = import_mangled<std::size_t()>("space::my_plugin::size"); //get the size function + + auto size = (*size_f)(); // get the size of the class +//] +//[import_class_value + auto value = import_mangled<int>(lib, "space::my_plugin::value"); +//] +//[import_class_ctor + auto cl = import_class<class alias, const std::string&>(lib, "space::my_plugin::some_class", size, "MyName"); +//] +//[import_class_name + auto name = import_mangled<const alias, std::string()>(lib, "name"); + std::cout << "Name: " << (cl->*name)() << std::endl; +//] +//[import_class_calc + auto calc = import_mangled<alias, float(float, float), int(int, int)>(lib, "calculate"); + std::cout << "Calc(float): " (cl->*calc)(5.f, 2.f) << std::endl; + std::cout << "Calc(int): " (cl->*calc)(5, 2) << std::endl; +//] +//[import_class_typeinfo + std::type_info &ti = cl.get_type_info(); +//] +} diff --git a/src/boost/libs/dll/example/mangled/my_cpp_plugin.hpp b/src/boost/libs/dll/example/mangled/my_cpp_plugin.hpp new file mode 100644 index 000000000..3f9e9ee16 --- /dev/null +++ b/src/boost/libs/dll/example/mangled/my_cpp_plugin.hpp @@ -0,0 +1,43 @@ +// Copyright 2016 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_DLL_MY_CPP_PLUGIN_API_HPP +#define BOOST_DLL_MY_CPP_PLUGIN_API_HPP + +//[cppplug +#include <string> + +namespace space { + +class BOOST_SYMBOL_EXPORT my_plugin +{ + std::string _name; +public: + std::string name() const; + float calculate(float x, float y); + int calculate(int, x, int y); + static std::size_t size(); + my_plugin(const std::string & name); + my_plugin(); + ~my_plugin_api(); + static int value; +}; + +} +//] + +std::string space::my_plugin_api::name() const {return _name;} +float space::my_plugin::calculate(float x, float y) {return x/y;} +int space::my_plugin::calculate(int, x, int y) {return x/y;} +std::size_t my_plugin::size() {return sizeof(my_plugin);} +space::my_plugin::my_plugin(const std::string & name) : _name(name) {} +space::my_plugin::my_plugin() : _name("Empty") {} +space::my_plugin::~my_plugin_api() {} +int space::my_plugin::value = 42; + + +#endif // BOOST_DLL_MY_PLUGIN_API_HPP + diff --git a/src/boost/libs/dll/example/mangled/smart_lib.cpp b/src/boost/libs/dll/example/mangled/smart_lib.cpp new file mode 100644 index 000000000..d8cb69c6e --- /dev/null +++ b/src/boost/libs/dll/example/mangled/smart_lib.cpp @@ -0,0 +1,58 @@ +// Copyright 2016 Klemens D. Morgenstern. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include "../b2_workarounds.hpp" // contains dll_test::replace_with_full_path + +//[smart_lib_setup +#include <boost/dll/smart_library.hpp> // for import_alias +#include <iostream> +#include <memory> + +namespace dll = boost::dll; + +struct alias; + +int main(int argc, char* argv[]) { + /*<-*/ b2_workarounds::argv_to_path_guard guard(argc, argv); /*->*/ + boost::dll::fs::path lib_path(argv[1]); // argv[1] contains path to directory with our plugin library + dll::smart_lib lib(lib_path); // smart library instance +//] +//[smart_lib_size + auto size_f = lib.get_function<std::size_t()>("space::my_plugin::size"); //get the size function + + auto size = size_f(); // get the size of the class + std::unique_ptr<char[], size> buffer(new char[size]); //allocate a buffer for the import + alias & inst = *reinterpret_cast<alias*>(buffer.get()); //cast it to our alias type. +//] +//[smart_lib_type_alias + lib.add_type_alias("space::my_plugin"); //add an alias, so i can import a class that is not declared here +//] +//[smart_lib_ctor + auto ctor = lib.get_constructor<alias(const std::string&)>(); //get the constructor + ctor.call_standard(&inst, "MyName"); //call the non-allocating constructor. The allocating-constructor is a non-portable feature +//] +//[smart_lib_name + auto name_f = lib.get_mem_fn<const alias, std::string()>("name");//import the name function + std::cout << "Name Call: " << (inst.*name_f)() << std::endl; +//] +//[smart_lib_calculate + //import both calculate functions + auto calc_f = lib.get_mem_fn<alias, float(float, float)>("calculate"); + auto calc_i = lib.get_mem_fn<alias, int(int, int)> ("calculate"); + + std::cout << "calc(float): " << (inst.*calc_f)(5., 2.) << std::endl; + std::cout << "calc(int) : " << (inst.*calc_f)(5, 2) << std::endl; +//] +//[smart_lib_var + auto & var = lib.get_variable<int>("space::my_plugin::value"); + cout << "value " << var << endl; +//] +//[smart_lib_dtor + auto dtor = lib.get_destructor<alias>(); //get the destructor + dtor.call_standard(&inst); + std::cout << "plugin->calculate(1.5, 1.5) call: " << plugin->calculate(1.5, 1.5) << std::endl; +} +//] diff --git a/src/boost/libs/dll/example/tutorial1/my_plugin_sum.cpp b/src/boost/libs/dll/example/tutorial1/my_plugin_sum.cpp new file mode 100644 index 000000000..09b78a643 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial1/my_plugin_sum.cpp @@ -0,0 +1,43 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> + + +//[plugcpp_my_plugin_sum +#include <boost/config.hpp> // for BOOST_SYMBOL_EXPORT +#include "../tutorial_common/my_plugin_api.hpp" + +namespace my_namespace { + +class my_plugin_sum : public my_plugin_api { +public: + my_plugin_sum() { + std::cout << "Constructing my_plugin_sum" << std::endl; + } + + std::string name() const { + return "sum"; + } + + float calculate(float x, float y) { + return x + y; + } + + ~my_plugin_sum() { + std::cout << "Destructing my_plugin_sum ;o)" << std::endl; + } +}; + +// Exporting `my_namespace::plugin` variable with alias name `plugin` +// (Has the same effect as `BOOST_DLL_ALIAS(my_namespace::plugin, plugin)`) +extern "C" BOOST_SYMBOL_EXPORT my_plugin_sum plugin; +my_plugin_sum plugin; + +} // namespace my_namespace + +//] diff --git a/src/boost/libs/dll/example/tutorial1/tutorial1.cpp b/src/boost/libs/dll/example/tutorial1/tutorial1.cpp new file mode 100644 index 000000000..2827a6399 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial1/tutorial1.cpp @@ -0,0 +1,31 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include "../b2_workarounds.hpp" // contains dll_test::replace_with_full_path + +//[callplugcpp_tutorial1 +#include <boost/dll/import.hpp> // for import_alias +#include <iostream> +#include "../tutorial_common/my_plugin_api.hpp" + +namespace dll = boost::dll; + +int main(int argc, char* argv[]) { + /*<-*/ b2_workarounds::argv_to_path_guard guard(argc, argv); /*->*/ + boost::dll::fs::path lib_path(argv[1]); // argv[1] contains path to directory with our plugin library + boost::shared_ptr<my_plugin_api> plugin; // variable to hold a pointer to plugin variable + std::cout << "Loading the plugin" << std::endl; + + plugin = dll::import<my_plugin_api>( // type of imported symbol is located between `<` and `>` + lib_path / "my_plugin_sum", // path to the library and library name + "plugin", // name of the symbol to import + dll::load_mode::append_decorations // makes `libmy_plugin_sum.so` or `my_plugin_sum.dll` from `my_plugin_sum` + ); + + std::cout << "plugin->calculate(1.5, 1.5) call: " << plugin->calculate(1.5, 1.5) << std::endl; +} +//] diff --git a/src/boost/libs/dll/example/tutorial2/my_plugin_aggregator.cpp b/src/boost/libs/dll/example/tutorial2/my_plugin_aggregator.cpp new file mode 100644 index 000000000..4247f89b7 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial2/my_plugin_aggregator.cpp @@ -0,0 +1,52 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> +#include <boost/make_shared.hpp> + +// MinGW related workaround +#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION + +//[plugcpp_my_plugin_aggregator +#include <boost/dll/alias.hpp> // for BOOST_DLL_ALIAS +#include "../tutorial_common/my_plugin_api.hpp" + +namespace my_namespace { + +class my_plugin_aggregator : public my_plugin_api { + float aggr_; + my_plugin_aggregator() : aggr_(0) {} + +public: + std::string name() const { + return "aggregator"; + } + + float calculate(float x, float y) { + aggr_ += x + y; + return aggr_; + } + + // Factory method + static boost::shared_ptr<my_plugin_aggregator> create() { + return boost::shared_ptr<my_plugin_aggregator>( + new my_plugin_aggregator() + ); + } +}; + + +BOOST_DLL_ALIAS( + my_namespace::my_plugin_aggregator::create, // <-- this function is exported with... + create_plugin // <-- ...this alias name +) + +} // namespace my_namespace +//] + + + diff --git a/src/boost/libs/dll/example/tutorial2/tutorial2.cpp b/src/boost/libs/dll/example/tutorial2/tutorial2.cpp new file mode 100644 index 000000000..83addb83f --- /dev/null +++ b/src/boost/libs/dll/example/tutorial2/tutorial2.cpp @@ -0,0 +1,36 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include "../b2_workarounds.hpp" + +//[callplugcpp_tutorial2 +#include <boost/dll/import.hpp> // for import_alias +#include <boost/function.hpp> +#include <iostream> +#include "../tutorial_common/my_plugin_api.hpp" + +namespace dll = boost::dll; + +int main(int argc, char* argv[]) { + /*<-*/ b2_workarounds::argv_to_path_guard guard(argc, argv); /*->*/ + boost::dll::fs::path shared_library_path(argv[1]); // argv[1] contains path to directory with our plugin library + shared_library_path /= "my_plugin_aggregator"; + typedef boost::shared_ptr<my_plugin_api> (pluginapi_create_t)(); + boost::function<pluginapi_create_t> creator; + + creator = boost::dll::import_alias<pluginapi_create_t>( // type of imported symbol must be explicitly specified + shared_library_path, // path to library + "create_plugin", // symbol to import + dll::load_mode::append_decorations // do append extensions and prefixes + ); + + boost::shared_ptr<my_plugin_api> plugin = creator(); + std::cout << "plugin->calculate(1.5, 1.5) call: " << plugin->calculate(1.5, 1.5) << std::endl; + std::cout << "plugin->calculate(1.5, 1.5) second call: " << plugin->calculate(1.5, 1.5) << std::endl; + std::cout << "Plugin Name: " << plugin->name() << std::endl; +} +//] diff --git a/src/boost/libs/dll/example/tutorial3/tutorial3.cpp b/src/boost/libs/dll/example/tutorial3/tutorial3.cpp new file mode 100644 index 000000000..c63615ba9 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial3/tutorial3.cpp @@ -0,0 +1,56 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include "../b2_workarounds.hpp" +//[callplugcpp_tutorial3 +#include <boost/dll/import.hpp> // for import_alias +#include <boost/make_shared.hpp> +#include <boost/function.hpp> +#include <iostream> +#include "../tutorial_common/my_plugin_api.hpp" + +namespace dll = boost::dll; + +std::size_t search_for_symbols(const std::vector<boost::dll::fs::path>& plugins) { + std::size_t plugins_found = 0; + + for (std::size_t i = 0; i < plugins.size(); ++i) { + std::cout << "Loading plugin: " << plugins[i] << '\n'; + dll::shared_library lib(plugins[i], dll::load_mode::append_decorations); + if (!lib.has("create_plugin")) { + // no such symbol + continue; + } + + // library has symbol, importing... + typedef boost::shared_ptr<my_plugin_api> (pluginapi_create_t)(); + boost::function<pluginapi_create_t> creator + = dll::import_alias<pluginapi_create_t>(boost::move(lib), "create_plugin"); + + std::cout << "Matching plugin name: " << creator()->name() << std::endl; + ++ plugins_found; + } + + return plugins_found; +} + +//] + +int main(int argc, char* argv[]) { + BOOST_ASSERT(argc >= 3); + std::vector<boost::dll::fs::path> plugins; + plugins.reserve(argc - 1); + for (int i = 1; i < argc; ++i) { + if (b2_workarounds::is_shared_library(argv[i])) { + plugins.push_back(argv[i]); + } + } + + const std::size_t res = search_for_symbols(plugins); + BOOST_ASSERT(res == 1); + (void)res; +} diff --git a/src/boost/libs/dll/example/tutorial4/load_self.cpp b/src/boost/libs/dll/example/tutorial4/load_self.cpp new file mode 100644 index 000000000..176bc01d3 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial4/load_self.cpp @@ -0,0 +1,39 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// MinGW related workaround +#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION + +//[plugcpp_my_plugin_load_self +#include <boost/dll/shared_library.hpp> // for shared_library +#include <boost/dll/runtime_symbol_info.hpp> // for program_location() +#include "static_plugin.hpp" // without this headers some compilers may optimize out the `create_plugin` symbol +#include <boost/function.hpp> +#include <iostream> + +namespace dll = boost::dll; + +int main() { + dll::shared_library self(dll::program_location()); + + std::cout << "Call function" << std::endl; + boost::function<boost::shared_ptr<my_plugin_api>()> creator + = self.get_alias<boost::shared_ptr<my_plugin_api>()>("create_plugin"); + + std::cout << "Computed Value: " << creator()->calculate(2, 2) << std::endl; + //<- + { + // This block is invisible for Quickbook documentation + float res = creator()->calculate(10, 10); + if (!(res > -0.0001 && res < 0.00001)) { + throw std::runtime_error("Failed check: res > -0.0001 && res < 0.00001"); + } + } + //-> +} + +//] diff --git a/src/boost/libs/dll/example/tutorial4/static_plugin.cpp b/src/boost/libs/dll/example/tutorial4/static_plugin.cpp new file mode 100644 index 000000000..84a43774b --- /dev/null +++ b/src/boost/libs/dll/example/tutorial4/static_plugin.cpp @@ -0,0 +1,42 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +//[plugcpp_my_plugin_staic_impl +#include "static_plugin.hpp" // this is essential, BOOST_SYMBOL_ALIAS must be seen in this file + +#include <boost/make_shared.hpp> +#include <iostream> + +namespace my_namespace { + +class my_plugin_static : public my_plugin_api { +public: + my_plugin_static() { + std::cout << "Constructing my_plugin_static" << std::endl; + } + + std::string name() const { + return "static"; + } + + float calculate(float x, float y) { + return x - y; + } + + ~my_plugin_static() { + std::cout << "Destructing my_plugin_static" << std::endl; + } +}; + +boost::shared_ptr<my_plugin_api> create_plugin() { + return boost::make_shared<my_plugin_static>(); +} + +} // namespace my_namespace + +//] + diff --git a/src/boost/libs/dll/example/tutorial4/static_plugin.hpp b/src/boost/libs/dll/example/tutorial4/static_plugin.hpp new file mode 100644 index 000000000..baf93ac20 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial4/static_plugin.hpp @@ -0,0 +1,22 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +//[plugcpp_my_plugin_static +#include <boost/dll/alias.hpp> // for BOOST_DLL_ALIAS +#include <boost/shared_ptr.hpp> +#include "../tutorial_common/my_plugin_api.hpp" + +namespace my_namespace { + boost::shared_ptr<my_plugin_api> create_plugin(); // Forward declaration +} // namespace my_namespace + +BOOST_DLL_ALIAS( + my_namespace::create_plugin, // <-- this function is exported with... + create_plugin // <-- ...this alias name +) +//] + diff --git a/src/boost/libs/dll/example/tutorial5/load_all.cpp b/src/boost/libs/dll/example/tutorial5/load_all.cpp new file mode 100644 index 000000000..7e7b30576 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial5/load_all.cpp @@ -0,0 +1,146 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// MinGW related workaround +#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION + +#include "../b2_workarounds.hpp" +#include "../tutorial4/static_plugin.hpp" +#include <boost/dll/runtime_symbol_info.hpp> // for program_location() +#include <boost/dll/shared_library.hpp> +#include <boost/make_shared.hpp> +#include <boost/container/map.hpp> +#include <boost/filesystem.hpp> +#include <iostream> + +//[plugcpp_plugins_collector_def +namespace dll = boost::dll; + +class plugins_collector { + // Name => plugin + typedef boost::container::map<std::string, dll::shared_library> plugins_t; + + boost::dll::fs::path plugins_directory_; + plugins_t plugins_; + + // loads all plugins in plugins_directory_ + void load_all(); + + // Gets `my_plugin_api` instance using "create_plugin" or "plugin" imports, + // stores plugin with its name in the `plugins_` map. + void insert_plugin(BOOST_RV_REF(dll::shared_library) lib); + +public: + plugins_collector(const boost::dll::fs::path& plugins_directory) + : plugins_directory_(plugins_directory) + { + load_all(); + } + + void print_plugins() const; + + std::size_t count() const; + // ... +}; +//] + + +//[plugcpp_plugins_collector_load_all +void plugins_collector::load_all() { + namespace fs = ::boost::dll::fs; + typedef fs::path::string_type string_type; + const string_type extension = dll::shared_library::suffix().native(); + + // Searching a folder for files with '.so' or '.dll' extension + fs::recursive_directory_iterator endit; + for (fs::recursive_directory_iterator it(plugins_directory_); it != endit; ++it) { + if (!fs::is_regular_file(*it)) { + continue; + } + /*<-*/ + if ( !b2_workarounds::is_shared_library((*it).path()) ) { + continue; + } + /*->*/ + // We found a file. Trying to load it + boost::dll::fs::error_code error; + dll::shared_library plugin(it->path(), error); + if (error) { + continue; + } + std::cout << "Loaded (" << plugin.native() << "):" << it->path() << '\n'; + + // Gets plugin using "create_plugin" or "plugin" function + insert_plugin(boost::move(plugin)); + } + + dll::shared_library plugin(dll::program_location()); + std::cout << "Loaded self\n"; + insert_plugin(boost::move(plugin)); +} +//] + +//[plugcpp_plugins_collector_insert_plugin +void plugins_collector::insert_plugin(BOOST_RV_REF(dll::shared_library) lib) { + std::string plugin_name; + if (lib.has("create_plugin")) { + plugin_name = lib.get_alias<boost::shared_ptr<my_plugin_api>()>("create_plugin")()->name(); + } else if (lib.has("plugin")) { + plugin_name = lib.get<my_plugin_api>("plugin").name(); + } else { + return; + } + + if (plugins_.find(plugin_name) == plugins_.cend()) { + plugins_[plugin_name] = boost::move(lib); + } +} +//] + +void plugins_collector::print_plugins() const { + plugins_t::const_iterator const end = plugins_.cend(); + for (plugins_t::const_iterator it = plugins_.cbegin(); it != end; ++it) { + std::cout << '(' << it->second.native() << "): " << it->first << '\n'; + } +} + +std::size_t plugins_collector::count() const { + return plugins_.size(); +} + + +//[plugcpp_load_all +int main(int argc, char* argv[]) { + /*<-*/ + BOOST_ASSERT(argc >= 3); + boost::dll::fs::path path1(argv[1]); + for (int i = 2; i < argc; ++i) { + boost::dll::fs::path path2(argv[i]); + boost::dll::fs::path res; + for (boost::dll::fs::path::iterator it1 = path1.begin(), it2 = path2.begin(); + it1 != path1.end() && it2 != path2.end() && *it1 == *it2; + ++it1, ++it2) + { + res /= *it1; + } + + path1 = res; + } + + std::string new_argv = path1.string(); + std::cout << "\nPlugins path: " << new_argv << ":\n"; + argv[1] = &new_argv[0]; + /*->*/ + plugins_collector plugins(argv[1]); + + std::cout << "\n\nUnique plugins " << plugins.count() << ":\n"; + plugins.print_plugins(); + // ... +//] + BOOST_ASSERT(plugins.count() >= 3); +} + diff --git a/src/boost/libs/dll/example/tutorial6/on_unload_lib.cpp b/src/boost/libs/dll/example/tutorial6/on_unload_lib.cpp new file mode 100644 index 000000000..f09ede95e --- /dev/null +++ b/src/boost/libs/dll/example/tutorial6/on_unload_lib.cpp @@ -0,0 +1,48 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// MinGW related workaround +#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION + +//[plugcpp_on_unload +#include <boost/dll/alias.hpp> // for BOOST_DLL_ALIAS +#include <boost/function.hpp> +#include <vector> + +namespace my_namespace { + +struct on_unload { + typedef boost::function<void()> callback_t; + typedef on_unload this_type; + + ~on_unload() { + for (std::size_t i = 0; i < callbacks_.size(); ++i) { + callback_t& function = callbacks_[i]; + function(); // calling the callback + } + } + + // not thread safe + static void add(const callback_t& function) { + static this_type instance; + instance.callbacks_.push_back(function); + } + +private: + std::vector<callback_t> callbacks_; + on_unload() {} // prohibit construction outside of the `add` function +}; + +// Exporting the static "add" function with name "on_unload" +BOOST_DLL_ALIAS(my_namespace::on_unload::add, on_unload) + +} // namespace my_namespace + +//] + + + diff --git a/src/boost/libs/dll/example/tutorial6/tutorial6.cpp b/src/boost/libs/dll/example/tutorial6/tutorial6.cpp new file mode 100644 index 000000000..87003f022 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial6/tutorial6.cpp @@ -0,0 +1,39 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include "../b2_workarounds.hpp" + +//[callplugcpp_tutorial6 +#include <boost/dll/import.hpp> +#include <boost/function.hpp> +#include <iostream> + +typedef boost::function<void()> callback_t; + +void print_unloaded() { + std::cout << "unloaded" << std::endl; +} + +int main(int argc, char* argv[]) { + // argv[1] contains full path to our plugin library + boost::dll::fs::path shared_library_path = /*<-*/ b2_workarounds::first_lib_from_argv(argc, argv); /*->*/ //=argv[1]; + + // loading library and getting a function from it + boost::function<void(const callback_t&)> on_unload + = boost::dll::import_alias<void(const callback_t&)>( + shared_library_path, "on_unload" + ); + + on_unload(&print_unloaded); // adding a callback + std::cout << "Before library unload." << std::endl; + + // Releasing last reference to the library, so that it gets unloaded + on_unload.clear(); + std::cout << "After library unload." << std::endl; +} +//] + diff --git a/src/boost/libs/dll/example/tutorial7/library1.cpp b/src/boost/libs/dll/example/tutorial7/library1.cpp new file mode 100644 index 000000000..fa48a5daf --- /dev/null +++ b/src/boost/libs/dll/example/tutorial7/library1.cpp @@ -0,0 +1,21 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// MinGW related workaround +#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION + +//[plugcpp_tutorial7_library1 +#include <boost/dll/alias.hpp> // for BOOST_DLL_ALIAS_SECTIONED +#include <iostream> +#include <string> + +void print(const std::string& s) { + std::cout << "Hello, " << s << '!' << std::endl; +} + +BOOST_DLL_ALIAS_SECTIONED(print, print_hello, Anna) +//] diff --git a/src/boost/libs/dll/example/tutorial7/library2.cpp b/src/boost/libs/dll/example/tutorial7/library2.cpp new file mode 100644 index 000000000..abdd60ff2 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial7/library2.cpp @@ -0,0 +1,26 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// MinGW related workaround +#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION + +//[plugcpp_tutorial7_library2 +#include <boost/dll/alias.hpp> // for BOOST_DLL_ALIAS_SECTIONED +#include <string> +#include <iostream> + +void print_howdy(const std::string& s) { + std::cout << "How're you doing, " << s << '?' << std::endl; +} + +void print_bored(const std::string& s) { + std::cout << "Are you bored, " << s << '?' << std::endl; +} + +BOOST_DLL_ALIAS_SECTIONED(print_howdy, howdy, Anna) +BOOST_DLL_ALIAS_SECTIONED(print_bored, are_you_bored, Anna) +//] diff --git a/src/boost/libs/dll/example/tutorial7/tutorial7.cpp b/src/boost/libs/dll/example/tutorial7/tutorial7.cpp new file mode 100644 index 000000000..e0186db27 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial7/tutorial7.cpp @@ -0,0 +1,48 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <vector> +#include "../b2_workarounds.hpp" + +//[callplugcpp_tutorial7 +#include <boost/dll/shared_library.hpp> +#include <boost/dll/library_info.hpp> +#include <iostream> + +void load_and_execute(const boost::dll::fs::path libraries[], std::size_t libs_count) { + const std::string username = "User"; + + for (std::size_t i = 0; i < libs_count; ++i) { + // Class `library_info` can extract information from a library + boost::dll::library_info inf(libraries[i]); + + // Getting symbols exported from 'Anna' section + std::vector<std::string> exports = inf.symbols("Anna"); + + // Loading library and importing symbols from it + boost::dll::shared_library lib(libraries[i]); + for (std::size_t j = 0; j < exports.size(); ++j) { + std::cout << "\nFunction '" << exports[j] << "' prints:\n\t"; + lib.get_alias<void(const std::string&)>(exports[j]) // importing function + (username); // calling function + } + } +} +//] + +int main(int argc, char* argv[]) { + /*<-*/ BOOST_ASSERT(argc >= 3); /*->*/ + std::vector<boost::dll::fs::path> libraries; + libraries.reserve(argc - 1); + for (int i = 1; i < argc; ++i) { + if (b2_workarounds::is_shared_library(argv[i])) { + libraries.push_back(argv[i]); + } + } + + load_and_execute(&libraries[0], libraries.size()); +} diff --git a/src/boost/libs/dll/example/tutorial8/refcounting_api.hpp b/src/boost/libs/dll/example/tutorial8/refcounting_api.hpp new file mode 100644 index 000000000..c9178110d --- /dev/null +++ b/src/boost/libs/dll/example/tutorial8/refcounting_api.hpp @@ -0,0 +1,77 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +//[plugcpp_my_plugin_refcounting_api +#include "../tutorial_common/my_plugin_api.hpp" +#include <boost/dll/config.hpp> + +class my_refcounting_api: public my_plugin_api { +public: + // Returns path to shared object that holds a plugin. + // Must be instantiated in plugin. + virtual boost::dll::fs::path location() const = 0; +}; +//] + + +//[plugcpp_library_holding_deleter_api_bind +#include <boost/shared_ptr.hpp> +#include <boost/make_shared.hpp> +#include <boost/dll/shared_library.hpp> + +struct library_holding_deleter { + boost::shared_ptr<boost::dll::shared_library> lib_; + + void operator()(my_refcounting_api* p) const { + delete p; + } +}; + +inline boost::shared_ptr<my_refcounting_api> bind(my_refcounting_api* plugin) { + // getting location of the shared library that holds the plugin + boost::dll::fs::path location = plugin->location(); + + // `make_shared` is an efficient way to create a shared pointer + boost::shared_ptr<boost::dll::shared_library> lib + = boost::make_shared<boost::dll::shared_library>(location); + + library_holding_deleter deleter; + deleter.lib_ = lib; + + return boost::shared_ptr<my_refcounting_api>( + plugin, deleter + ); +} +//] + +//[plugcpp_get_plugin_refcounting +#include <boost/dll/import.hpp> +#include <boost/function.hpp> +inline boost::shared_ptr<my_refcounting_api> get_plugin( + boost::dll::fs::path path, const char* func_name) +{ + typedef my_refcounting_api*(func_t)(); + boost::function<func_t> creator = boost::dll::import_alias<func_t>( + path, + func_name, + boost::dll::load_mode::append_decorations // will be ignored for executable + ); + + // `plugin` does not hold a reference to shared library. If `creator` will go out of scope, + // then `plugin` can not be used. + my_refcounting_api* plugin = creator(); + + // Returned variable holds a reference to + // shared_library and it is safe to use it. + return bind( plugin ); + + // `creator` goes out of scope here and will be destroyed. +} + +//] + + diff --git a/src/boost/libs/dll/example/tutorial8/refcounting_plugin.cpp b/src/boost/libs/dll/example/tutorial8/refcounting_plugin.cpp new file mode 100644 index 000000000..bb52cdfa8 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial8/refcounting_plugin.cpp @@ -0,0 +1,47 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// MinGW related workaround +#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION + +//[plugcpp_my_plugin_refcounting +#include "refcounting_plugin.hpp" +#include <boost/dll/runtime_symbol_info.hpp> // for this_line_location() + +namespace my_namespace { + +class my_plugin_refcounting : public my_refcounting_api { +public: + // Must be instantiated in plugin + boost::dll::fs::path location() const { + return boost::dll::this_line_location(); // location of this plugin + } + + std::string name() const { + return "refcounting"; + } + + // ... + //<- + // This block is invisible for Quickbook documentation + float calculate(float /*x*/, float /*y*/) { + return 0; + } + //-> +}; + +} // namespace my_namespace + +// Factory method. Returns *simple pointer*! +my_refcounting_api* create() { + return new my_namespace::my_plugin_refcounting(); +} + +//] + + + diff --git a/src/boost/libs/dll/example/tutorial8/refcounting_plugin.hpp b/src/boost/libs/dll/example/tutorial8/refcounting_plugin.hpp new file mode 100644 index 000000000..990bd2141 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial8/refcounting_plugin.hpp @@ -0,0 +1,17 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +//[plugcpp_my_plugin_refcounting_hpp +#include "refcounting_api.hpp" +#include <boost/dll/alias.hpp> // for BOOST_DLL_ALIAS + +my_refcounting_api* create(); // defined in plugin +BOOST_DLL_ALIAS(create, create_refc_plugin) +//] + + + diff --git a/src/boost/libs/dll/example/tutorial8/tutorial8.cpp b/src/boost/libs/dll/example/tutorial8/tutorial8.cpp new file mode 100644 index 000000000..ef169a990 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial8/tutorial8.cpp @@ -0,0 +1,25 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include "../b2_workarounds.hpp" + +//[callplugcpp_tutorial8 +#include <iostream> +#include "refcounting_api.hpp" + +int main(int argc, char* argv[]) { + /*<-*/ b2_workarounds::argv_to_path_guard guard(argc, argv); /*->*/ + boost::shared_ptr<my_refcounting_api> plugin = get_plugin( + boost::dll::fs::path(argv[1]) / "refcounting_plugin", + "create_refc_plugin" + ); + + std::cout << "Plugin name: " << plugin->name() + << ", \nlocation: " << plugin->location() + << std::endl; +} +//] diff --git a/src/boost/libs/dll/example/tutorial8/tutorial8_static.cpp b/src/boost/libs/dll/example/tutorial8/tutorial8_static.cpp new file mode 100644 index 000000000..810d322f5 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial8/tutorial8_static.cpp @@ -0,0 +1,23 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +//[callplugcpp_tutorial8_static +#include <boost/dll/runtime_symbol_info.hpp> // program_location() +#include <iostream> +#include "refcounting_plugin.hpp" + +int main() { + boost::shared_ptr<my_refcounting_api> plugin = get_plugin( + boost::dll::program_location(), + "create_refc_plugin" + ); + + std::cout << "Plugin name: " << plugin->name() + << ", \nlocation: " << plugin->location() + << std::endl; +} +//] diff --git a/src/boost/libs/dll/example/tutorial9/tutorial9.cpp b/src/boost/libs/dll/example/tutorial9/tutorial9.cpp new file mode 100644 index 000000000..2f4f5efab --- /dev/null +++ b/src/boost/libs/dll/example/tutorial9/tutorial9.cpp @@ -0,0 +1,60 @@ +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/predef/os.h> +#if BOOST_OS_WINDOWS + +//[callplugcpp_tutorial9 +#include <boost/dll/import.hpp> // for dll::import +#include <boost/dll/shared_library.hpp> // for dll::shared_library +#include <boost/function.hpp> +#include <iostream> +#include <windows.h> + +namespace dll = boost::dll; + +int main() { + typedef HANDLE(__stdcall GetStdHandle_t)(DWORD ); // function signature with calling convention + + // OPTION #0, requires C++11 compatible compiler that understands GetStdHandle_t signature. +/*<-*/ +#if defined(_MSC_VER) && !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) /*->*/ + auto get_std_handle = dll::import<GetStdHandle_t>( + "Kernel32.dll", + "GetStdHandle", + boost::dll::load_mode::search_system_folders + ); + std::cout << "0.0 GetStdHandle() returned " << get_std_handle(STD_OUTPUT_HANDLE) << std::endl; + + // You may put the `get_std_handle` into boost::function<>. But boost::function<Signature> can not compile with + // Signature template parameter that contains calling conventions, so you'll have to remove the calling convention. + boost::function<HANDLE(DWORD)> get_std_handle2 = get_std_handle; + std::cout << "0.1 GetStdHandle() returned " << get_std_handle2(STD_OUTPUT_HANDLE) << std::endl; +/*<-*/ +#endif /*->*/ + + // OPTION #1, does not require C++11. But without C++11 dll::import<> can not handle calling conventions, + // so you'll need to hand write the import. + dll::shared_library lib("Kernel32.dll", dll::load_mode::search_system_folders); + GetStdHandle_t& func = lib.get<GetStdHandle_t>("GetStdHandle"); + + // Here `func` does not keep a reference to `lib`, you'll have to deal with that on your own. + std::cout << "1.0 GetStdHandle() returned " << func(STD_OUTPUT_HANDLE) << std::endl; + + return 0; +} + +//] + +#else // BOOST_WINDOWS + +#include <boost/dll/shared_library.hpp> // for dll::shared_library + +int main() { + return 0; +} + +#endif // BOOST_WINDOWS diff --git a/src/boost/libs/dll/example/tutorial_common/my_plugin_api.hpp b/src/boost/libs/dll/example/tutorial_common/my_plugin_api.hpp new file mode 100644 index 000000000..d8fe85825 --- /dev/null +++ b/src/boost/libs/dll/example/tutorial_common/my_plugin_api.hpp @@ -0,0 +1,24 @@ +// Copyright 2016-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_DLL_MY_PLUGIN_API_HPP +#define BOOST_DLL_MY_PLUGIN_API_HPP + +//[plugapi +#include <boost/config.hpp> +#include <string> + +class BOOST_SYMBOL_VISIBLE my_plugin_api { +public: + virtual std::string name() const = 0; + virtual float calculate(float x, float y) = 0; + + virtual ~my_plugin_api() {} +}; +//] + +#endif // BOOST_DLL_MY_PLUGIN_API_HPP + diff --git a/src/boost/libs/dll/index.html b/src/boost/libs/dll/index.html new file mode 100644 index 000000000..508869790 --- /dev/null +++ b/src/boost/libs/dll/index.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<!-- + Copyright (c) 2014-2015 Antony Polukhin + antoshkka at gmail dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +--> +<html> +<head> +<meta charset="utf-8"> +<meta http-equiv="refresh" content="0; url=../../doc/html/boost_dll.html"> +<title>Boost.TypeIndex</title> +<style> + body { + background: #fff; + color: #000; + } + a { + color: #00f; + text-decoration: none; + } +</style> +</head> +<body> + <p> + Automatic redirection failed, please go to + <a href="../../doc/html/boost_dll.html">../../doc/html/boost_dll.html</a> + </p> + <p> + © 2014-2015 Antony Polukhin + </p> +</body> +</html> diff --git a/src/boost/libs/dll/meta/libraries.json b/src/boost/libs/dll/meta/libraries.json new file mode 100644 index 000000000..ebe057308 --- /dev/null +++ b/src/boost/libs/dll/meta/libraries.json @@ -0,0 +1,15 @@ +{ + "key": "dll", + "name": "DLL", + "authors": [ + "Antony Polukhin", "Renato Tegon Forti" + ], + "maintainers": [ + "Antony Polukhin <antoshkka -at- gmail.com>" + ], + "description": "Library for comfortable work with DLL and DSO.", + "std": [ "proposal" ], + "category": [ + "System" + ] +} diff --git a/src/boost/libs/dll/test/Jamfile.v2 b/src/boost/libs/dll/test/Jamfile.v2 new file mode 100644 index 000000000..b7ea3909d --- /dev/null +++ b/src/boost/libs/dll/test/Jamfile.v2 @@ -0,0 +1,95 @@ +# +# Copyright Renato Tegon Forti, Antony Polukhin 2011 - 2019. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# + +# For more information, see http://www.boost.org + +# bring in rules for testing +import testing ; +import path ; + +local RDYNAMIC = <target-os>freebsd:<linkflags>"-rdynamic" <target-os>solaris:<linkflags>"-Bdynamic" <target-os>aix:<linkflags>"-rdynamic" + <target-os>qnxnto,<toolset>qcc:<linkflags>"-Bdynamic" <target-os>qnxnto,<toolset>gcc:<linkflags>"-rdynamic" + <target-os>android:<linkflags>"-rdynamic" <target-os>linux:<linkflags>"-rdynamic" <target-os>darwin,<toolset>gcc:<linkflags>"-dynamic" + <target-os>darwin,<toolset>clang:<linkflags>"-rdynamic" <target-os>iphone:<linkflags>"-rdynamic" ; + + +# Static library that is not linked with any of the boost libs +lib static_plugin : ../example/tutorial4/static_plugin.cpp : <link>static <define>BOOST_SYSTEM_NO_DEPRECATED $(RDYNAMIC) ; +lib static_refcounting_plugin : ../example/tutorial8/refcounting_plugin.cpp : <link>static <define>BOOST_SYSTEM_NO_DEPRECATED <variant>release $(RDYNAMIC) ; + + +project + : source-location . + : requirements + + # linux + <target-os>linux:<linkflags>"-ldl" + <toolset>gcc:<cxxflags>"-Wall -Wextra -pedantic -Wno-long-long" + + # others + <local-visibility>hidden + <library>/boost/filesystem//boost_filesystem + <library>/boost/system//boost_system + <threading>multi + <define>BOOST_SYSTEM_NO_DEPRECATED + ; +{ + + # our test lib for shared library tests + lib test_library : test_library.cpp : <link>shared ; + lib getting_started_library : ../example/getting_started_library.cpp : <link>shared ; + lib my_plugin_sum : ../example/tutorial1/my_plugin_sum.cpp : <link>shared ; + lib my_plugin_aggregator : ../example/tutorial2/my_plugin_aggregator.cpp : <link>shared ; + lib on_unload_lib : ../example/tutorial6/on_unload_lib.cpp : <link>shared ; + lib library1 : ../example/tutorial7/library1.cpp : <link>shared ; + lib library2 : ../example/tutorial7/library2.cpp : <link>shared ; + lib refcounting_plugin : ../example/tutorial8/refcounting_plugin.cpp : <link>shared ; + lib cpp_plugin : cpp_test_library.cpp : <link>shared ; + + test-suite boostdll + : + [ run link1.cpp link2.cpp : : : : validate_link ] + [ run shared_library_load_test.cpp : : library1 test_library : <link>shared ] + [ run shared_library_search_symbol_test.cpp : : test_library : $(RDYNAMIC) <link>shared ] + [ run shared_library_get_symbol_test.cpp : : test_library : $(RDYNAMIC) <link>shared ] + [ run shared_library_get_symbol_test.cpp + : + : test_library + : $(RDYNAMIC) <target-os>windows:<define>BOOST_USE_WINDOWS_H <link>shared + : get_symbol_windows_h_forced + ] + [ run symbol_runtime_info_test.cpp : : test_library : $(RDYNAMIC) <link>shared ] + [ run shared_library_errors.cpp : : test_library : <test-info>always_show_run_output <link>shared ] + [ run structures_tests.cpp ] + [ run library_info_test.cpp ../example/tutorial4/static_plugin.cpp : : test_library : <test-info>always_show_run_output <link>shared ] + [ run ../example/getting_started.cpp : : getting_started_library : <link>shared ] + [ run ../example/tutorial1/tutorial1.cpp : : my_plugin_sum : <link>shared ] + [ run ../example/tutorial2/tutorial2.cpp : : my_plugin_aggregator : <link>shared ] + [ run ../example/tutorial3/tutorial3.cpp : : my_plugin_aggregator my_plugin_sum : <link>shared ] + [ run ../example/tutorial4/load_self.cpp ../example/tutorial4/static_plugin.cpp + : : : <variant>release $(RDYNAMIC) + ] + [ run ../example/tutorial5/load_all.cpp ../example/tutorial4/static_plugin.cpp + : : getting_started_library my_plugin_aggregator my_plugin_sum : $(RDYNAMIC) <link>shared + ] + [ run ../example/tutorial6/tutorial6.cpp : : on_unload_lib : <link>shared ] + [ run ../example/tutorial7/tutorial7.cpp : : library1 library2 : <link>shared ] + [ run ../example/tutorial8/tutorial8.cpp : : refcounting_plugin : <link>shared ] + [ run ../example/tutorial8/tutorial8_static.cpp : : : <link>static <variant>release $(RDYNAMIC) <test-info>always_show_run_output <library>static_refcounting_plugin + # Known problem: unsupported __dllexport__ with weak symbols + GNU linker features (no non-weak unresolved symbols in executable => no need to link libraries) + <target-os>windows,<toolset>gcc:<build>no + ] + [ run ../example/tutorial9/tutorial9.cpp ] + # test for shared libraries + [ compile-fail section_name_too_big.cpp ] + [ run shared_library_concurrent_load_test.cpp /boost/thread//boost_thread : : library1 library2 my_plugin_aggregator refcounting_plugin : <link>shared ] + [ run cpp_mangle_test.cpp : : cpp_plugin ] + [ run cpp_load_test.cpp : : cpp_plugin ] + [ run cpp_import_test.cpp : : cpp_plugin ] + [ run template_method_linux_test.cpp : : cpp_plugin ] + ; +} diff --git a/src/boost/libs/dll/test/cpp_import_class_test.cpp b/src/boost/libs/dll/test/cpp_import_class_test.cpp new file mode 100644 index 000000000..60e0adc0b --- /dev/null +++ b/src/boost/libs/dll/test/cpp_import_class_test.cpp @@ -0,0 +1,115 @@ +// Copyright 2016 Klemens Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + + +#include <boost/predef.h> + +#if (__cplusplus >= 201402L) || (BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(14,0,0)) + +#include "../example/b2_workarounds.hpp" + +#include <iostream> + +using namespace std; + +#include <boost/dll/smart_library.hpp> +#include <boost/dll/import_mangled.hpp> +#include <boost/dll/import_class.hpp> + +#include <boost/core/lightweight_test.hpp> +#include <boost/filesystem.hpp> +#include <boost/variant.hpp> +#include <boost/function.hpp> + +#define L cout << __LINE__ << endl; + +int main(int argc, char* argv[]) +{ + using namespace boost::dll; + using namespace boost::dll::experimental; + boost::dll::fs::path pt = b2_workarounds::first_lib_from_argv(argc, argv); + + BOOST_TEST(!pt.empty()); + std::cout << "Library: " << pt << std::endl; + + smart_library sm(pt); + + auto static_val = import_mangled<int>(sm, "some_space::some_class::value"); + + std::cout << "--------------------- Entry Points ------------------------\n" << std::endl; + for (auto &s : sm.symbol_storage().get_storage()) + std::cout << s.demangled << std::endl; + + std::cout << "-----------------------------------------------------------\n\n" << std::endl; + + + auto sp_variable = import_mangled<double>(sm, "some_space::variable"); + + auto unscoped_var = import_mangled<int>(sm, "unscoped_var"); + + std::size_t type_size = *import_mangled<std::size_t>(sm, "some_space::size_of_some_class"); + { + +#if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows + class override_class{}; + auto cl = import_class<override_class, int>(sm, "some_space::some_class", type_size, 42); +#else + auto cl = import_class<class override_class, int>(sm, "some_space::some_class", type_size, 42); +#endif + BOOST_TEST(!cl.is_copy_assignable()); + BOOST_TEST(!cl.is_copy_constructible()); + + BOOST_TEST( cl.is_move_assignable()); + BOOST_TEST( cl.is_move_constructible()); + + BOOST_TEST(*static_val == 42); + + auto i = cl.call<const override_class, int()>("get")(); + BOOST_TEST(i == 456); + cl.call<void(int)>("set")(42); + i = 0; + i = cl.call<const override_class, int()>("get")(); + BOOST_TEST(i == 42); + + auto func = import_mangled< + override_class, double(double, double), int(int, int), + volatile override_class, int(int, int), + const volatile override_class, double(double, double)>(sm, "func"); + + + + BOOST_TEST((cl->*func)(3.,2.) == 6.); + BOOST_TEST((cl->*func)(1 ,2 ) == 3 ); + + auto fun2 = cl.import<double(double, double), int(int, int)>("func"); + + BOOST_TEST((cl->*fun2)(3.,2.) == 6.); + BOOST_TEST((cl->*fun2)(5 ,2 ) == 7 ); + + //test if it binds. + boost::function<int(override_class* const, int, int)> mem_fn_obj = func; + + + const std::type_info & ti = cl.get_type_info(); + std::string imp_name = boost::core::demangle(ti.name()); +#if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows + std::string exp_name = "struct some_space::some_class"; +#else + std::string exp_name = "some_space::some_class"; +#endif + BOOST_TEST(imp_name == exp_name); + } + + BOOST_TEST(*static_val == 0); + + return boost::report_errors(); +} + +#else +int main() {return 0;} +#endif diff --git a/src/boost/libs/dll/test/cpp_import_test.cpp b/src/boost/libs/dll/test/cpp_import_test.cpp new file mode 100644 index 000000000..b6005d058 --- /dev/null +++ b/src/boost/libs/dll/test/cpp_import_test.cpp @@ -0,0 +1,81 @@ +// Copyright 2016 Klemens Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include <boost/predef.h> + +#if (__cplusplus >= 201402L) || (BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(14,0,0)) + +#include "../example/b2_workarounds.hpp" + +#include <boost/dll/smart_library.hpp> +#include <boost/dll/import_mangled.hpp> + +#include <boost/core/lightweight_test.hpp> +#include <boost/filesystem.hpp> +#include <boost/variant.hpp> +#include <boost/function.hpp> + +#include <iostream> + +struct override_class +{ + int arr[32]; +}; + + +int main(int argc, char* argv[]) +{ + using namespace boost::dll; + using namespace boost::dll::experimental; + boost::dll::fs::path pt = b2_workarounds::first_lib_from_argv(argc, argv); + + BOOST_TEST(!pt.empty()); + std::cout << "Library: " << pt << std::endl; + + smart_library sm(pt); + + auto sp_variable = import_mangled<double>(sm, "some_space::variable"); + + auto unscoped_var = import_mangled<int>(sm, "unscoped_var"); + + + auto ovl = import_mangled<void(int), void(double)>(sm, "overloaded"); + + ovl(12); + BOOST_TEST(*unscoped_var == 12); + ovl(5.0); + BOOST_TEST(*sp_variable == 5.0); + + boost::function<void(int)> f_test = ovl;//test if it binds + f_test(-2); + BOOST_TEST(*unscoped_var == -2); + + sm.add_type_alias<override_class>("some_space::some_class"); + + auto func = import_mangled< + override_class, double(double, double), int(int, int), + volatile override_class, int(int, int), + const volatile override_class, double(double, double)>(sm, "func"); + + override_class override_class_varible{}; + + override_class *ov = &override_class_varible; + volatile override_class *ovv = ov; + const volatile override_class *ovcv = ov; + + BOOST_TEST(func(ov, 3.,2.) == 6.); + BOOST_TEST(func(ov, 1,2 ) == 3 ); + BOOST_TEST(func(ovv, 10,2) == 8 ); + BOOST_TEST(func(ovcv, 9,2) == 4.5 ); + + return boost::report_errors(); +} + +#else +int main() {return 0;} +#endif diff --git a/src/boost/libs/dll/test/cpp_load_test.cpp b/src/boost/libs/dll/test/cpp_load_test.cpp new file mode 100644 index 000000000..a95a9afdc --- /dev/null +++ b/src/boost/libs/dll/test/cpp_load_test.cpp @@ -0,0 +1,228 @@ +// Copyright 2016 Klemens Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include <boost/predef.h> + +#if (__cplusplus >= 201402L) || (BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(14,0,0)) + +#include "../example/b2_workarounds.hpp" + +#include <boost/dll/smart_library.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/filesystem.hpp> +#include <boost/variant.hpp> + +#include <iostream> + +struct override_class +{ + int arr[32]; +}; + + +int main(int argc, char* argv[]) +{ + using namespace boost::dll; + using namespace boost::dll::experimental; + boost::dll::fs::path pt = b2_workarounds::first_lib_from_argv(argc, argv); + + BOOST_TEST(!pt.empty()); + std::cout << "Library: " << pt << std::endl; + std::cerr << 1 << ' '; + smart_library sm(pt); + + auto& unscoped_var = sm.get_variable<int>("unscoped_var"); + BOOST_TEST(unscoped_var == 42); + std::cerr << 2 << ' '; + auto& unscoped_c_var = sm.get_variable<const double>("unscoped_c_var"); + BOOST_TEST(unscoped_c_var == 1.234); + + std::cerr << 3 << ' '; + auto& sp_variable = sm.get_variable<double>("some_space::variable"); + BOOST_TEST(sp_variable == 0.2); + + std::cerr << 4 << ' '; + auto scoped_fun = sm.get_function<const int&()>("some_space::scoped_fun"); + BOOST_TEST(scoped_fun != nullptr); + { std::cerr << 5 << ' '; + auto &res = scoped_fun(); + const int expected = 0xDEADBEEF; + BOOST_TEST(res == expected); + } + std::cerr << 6 << ' '; + auto ovl1 = sm.get_function<void(int)> ("overloaded"); + auto ovl2 = sm.get_function<void(double)>("overloaded"); + std::cerr << 7 << ' '; + BOOST_TEST(ovl1 != nullptr); + BOOST_TEST(ovl2 != nullptr); + BOOST_TEST(reinterpret_cast<void*>(ovl1) != reinterpret_cast<void*>(ovl2)); + std::cerr << 8 << ' '; + ovl1(12); + BOOST_TEST(unscoped_var == 12); + ovl2(5.0); + BOOST_TEST(sp_variable == 5.0); + std::cerr << 9 << ' '; + + +// TODO: ms.get_name on Clang has space after comma `boost::variant<double, int>` +#if !(defined(BOOST_TRAVISCI_BUILD) && defined(_MSC_VER) && defined(BOOST_CLANG)) + auto var1 = sm.get_function<void(boost::variant<int, double> &)>("use_variant"); + auto var2 = sm.get_function<void(boost::variant<double, int> &)>("use_variant"); + std::cerr << 10 << ' '; + BOOST_TEST(var1 != nullptr); + BOOST_TEST(var2 != nullptr); + BOOST_TEST(reinterpret_cast<void*>(var1) != reinterpret_cast<void*>(var2)); + + { + boost::variant<int, double> v1 = 232.22; + boost::variant<double, int> v2 = -1; + std::cerr << 11 << ' '; + var1(v1); + var2(v2); + + struct : boost::static_visitor<void> + { + void operator()(double) {BOOST_TEST(false);} + void operator()(int i) {BOOST_TEST(i == 42);} + } vis1; + + struct : boost::static_visitor<void> + { + void operator()(double d) {BOOST_TEST(d == 3.124);} + void operator()(int ) {BOOST_TEST(false);} + } vis2; + + boost::apply_visitor(vis1, v1); + boost::apply_visitor(vis2, v2); + + } +#endif + std::cerr << 12 << ' '; + /* now test the class stuff */ + + //first we import and test the global variables + + auto& father_val = sm.get_variable<int>("some_space::father_value"); + auto& static_val = sm.get_variable<int>("some_space::some_class::value"); + BOOST_TEST(father_val == 12); + BOOST_TEST(static_val == -1); + std::cerr << 13 << ' '; + //now get the static function. + auto set_value = sm.get_function<void(const int &)>("some_space::some_class::set_value"); + BOOST_TEST(set_value != nullptr); + std::cerr << 14 << ' '; + set_value(42); + BOOST_TEST(static_val == 42); //alright, static method works. + + + //alright, now import the class members + //first add the type alias. + sm.add_type_alias<override_class>("some_space::some_class"); + std::cerr << 15 << ' '; + auto set = sm.get_mem_fn<override_class, void(int)>("set"); + + std::cerr << 16 << ' '; + try { + sm.get_mem_fn<override_class, int()>("get"); + BOOST_TEST(false); + } catch(boost::dll::fs::system_error &) {} + auto get = sm.get_mem_fn<const override_class, int()>("get"); + std::cerr << 17 << ' '; + BOOST_TEST(get != nullptr); + BOOST_TEST(set != nullptr); + std::cerr << 18 << ' '; + auto func_dd = sm.get_mem_fn<override_class, double(double, double)>("func"); + auto func_ii = sm.get_mem_fn<override_class, int(int, int)> ("func"); + auto func_iiv = sm.get_mem_fn<volatile override_class, int(int, int)> ("func"); + auto func_ddc = sm.get_mem_fn<const volatile override_class, double(double, double)>("func"); + + std::cerr << 19 << ' '; + BOOST_TEST(func_dd != nullptr); + BOOST_TEST(func_ii != nullptr); + + std::cerr << 20 << ' '; + auto ctor_v = sm.get_constructor<override_class()>(); + auto ctor_i = sm.get_constructor<override_class(int)>(); + + auto dtor = sm.get_destructor<override_class>(); + std::cerr << 21 << ' '; + //actually never used. + if (ctor_v.has_allocating()) + { + //allocate + auto p = ctor_v.call_allocating(); + + //assert it works + auto val = (p->*get)(); + BOOST_TEST(val == 123); + //deallocate + dtor.call_deleting(p); + //now i cannot assert that it deletes, since it would crash. + } + //More tests to assure the correct this-ptr + std::cerr << 22 << ' '; + typedef override_class * override_class_p; + override_class_p &this_dll = sm.shared_lib().get<override_class_p>("this_"); + + std::cerr << 23 << ' '; + //ok, now load the ctor/dtor + override_class oc; + + override_class_p this_exe = &oc; + + for (auto& i : oc.arr) { + i = 0; + } + std::cerr << 24 << ' '; + + BOOST_TEST((oc.*get)() == 0); BOOST_TEST(this_dll == this_exe); + + ctor_i.call_standard(&oc, 12); BOOST_TEST(this_dll == this_exe); + + BOOST_TEST(static_val == 12); + BOOST_TEST((oc.*get)() == 456); BOOST_TEST(this_dll == this_exe); + (oc.*set)(42); + BOOST_TEST((oc.*get)() == 42); BOOST_TEST(this_dll == this_exe); + std::cerr << 25 << ' '; + + BOOST_TEST((oc.*func_dd)(3,2) == 6); BOOST_TEST(this_dll == this_exe); + BOOST_TEST((oc.*func_ii)(1,2) == 3); BOOST_TEST(this_dll == this_exe); + BOOST_TEST((oc.*func_ddc)(10,2) == 5); BOOST_TEST(this_dll == this_exe); + BOOST_TEST((oc.*func_iiv)(9,2) == 7); BOOST_TEST(this_dll == this_exe); + std::cerr << 26 << ' '; + dtor.call_standard(&oc); BOOST_TEST(this_dll == this_exe); + BOOST_TEST(static_val == 0); + +#ifndef BOOST_NO_RTTI + const auto& ti = sm.get_type_info<override_class>(); + BOOST_TEST(ti.name() != nullptr); +#endif + std::cerr << 27 << ' '; + //test the ovls helper. + { + namespace ex = boost::dll::experimental; + auto &var = ex::get<double>(sm, "some_space::variable"); + BOOST_TEST(&var == &sp_variable); + + auto fun = ex::get<void(int)>(sm, "overloaded"); + BOOST_TEST(fun == ovl1); + + auto func_ii = sm.get_mem_fn<override_class, int(int, int)> ("func"); + + auto mem_fn = ex::get<override_class, int(int, int)>(sm, "func"); + + BOOST_TEST(mem_fn == func_ii); + } + + std::cerr << 28 << ' '; + return boost::report_errors(); +} + +#else +int main() {return 0;} +#endif diff --git a/src/boost/libs/dll/test/cpp_mangle_test.cpp b/src/boost/libs/dll/test/cpp_mangle_test.cpp new file mode 100644 index 000000000..1b235877b --- /dev/null +++ b/src/boost/libs/dll/test/cpp_mangle_test.cpp @@ -0,0 +1,133 @@ +// Copyright 2016 Klemens Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include <boost/predef.h> + +#if (__cplusplus >= 201402L) || (BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(14,0,0)) + +#include "../example/b2_workarounds.hpp" + +#include <boost/dll/smart_library.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/filesystem.hpp> +#include <boost/variant.hpp> + +#include <iostream> + + +struct override_class {}; + + +int main(int argc, char* argv[]) +{ + using namespace boost::dll; + using mangled_storage = detail::mangled_storage_impl; + + boost::dll::fs::path pt = b2_workarounds::first_lib_from_argv(argc, argv); + + std::cout << "Library: " << pt << std::endl; + library_info lib{pt}; + + mangled_storage ms(lib); + + std::cout << "Symbols: " << std::endl; + + for (auto &s : ms.get_storage()) + { + std::cout << s.demangled << std::endl; + } + + std::string v; + v = ms.get_variable<double>("some_space::variable"); + + BOOST_TEST(!v.empty()); //check if a symbols was found. + BOOST_TEST(v != "some_space::variable"); //demangle is different + + v = ms.get_variable<double>("some_space::variable_typo"); + BOOST_TEST(v.empty()); + + + v = ms.get_variable<const double>("unscoped_c_var"); + + BOOST_TEST(!v.empty()); //check if a symbols was found. + + v = ms.get_variable<int>("unscoped_var"); + + BOOST_TEST(!v.empty()); //check if a symbols was found. + + + v = ms.get_function<const int &()>("some_space::scoped_fun"); + + BOOST_TEST(!v.empty()); + BOOST_TEST(v != "some_space::scoped_fun"); + + + auto v1 = ms.get_function<void(const double)>("overloaded"); + auto v2 = ms.get_function<void(const volatile int)>("overloaded"); + BOOST_TEST(!v1.empty()); + BOOST_TEST(!v2.empty()); + BOOST_TEST(v1 != v2); + + v = ms.get_variable<int>("some_space::some_class::value"); + BOOST_TEST(!v.empty()); + BOOST_TEST(v != "some_space::some_class::value"); + + v = ms.get_function<void(const int &)>("some_space::some_class::set_value"); + + BOOST_TEST(!v.empty()); + BOOST_TEST(v != "some_space::some_class::set_value"); + + + + ms.add_alias<override_class>("some_space::some_class"); + + auto ctor1 = ms.get_constructor<override_class()>(); + BOOST_TEST(!ctor1.empty()); + + auto ctor2 = ms.get_constructor<override_class(int)>(); + BOOST_TEST(!ctor2.empty()); + + + v = ms.get_mem_fn<override_class, double(double, double)>("func"); + BOOST_TEST(!v.empty()); + + v = ms.get_mem_fn<override_class, int(int, int)>("func"); + BOOST_TEST(!v.empty()); + + + auto dtor = ms.get_destructor<override_class>(); + + BOOST_TEST(!dtor.empty()); + +// TODO: ms.get_name on Clang has space after comma `boost::variant<double, int>` +#if !(defined(BOOST_TRAVISCI_BUILD) && defined(_MSC_VER) && defined(BOOST_CLANG)) + auto var1 = ms.get_function<void(boost::variant<int, double> &)>("use_variant"); + auto var2 = ms.get_function<void(boost::variant<double, int> &)>("use_variant"); + + BOOST_TEST(!var1.empty()); + BOOST_TEST(!var2.empty()); +#endif + +#ifndef BOOST_NO_RTTI + +#if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows + auto vtable = ms.get_vtable<override_class>(); + BOOST_TEST(!vtable.empty()); +#else + auto ti = ms.get_type_info<override_class>(); + BOOST_TEST(!ti.empty()); +#endif + +#endif // #ifndef BOOST_NO_RTTI + + return boost::report_errors(); +} + +#else +int main() {return 0;} +#endif diff --git a/src/boost/libs/dll/test/cpp_test_library.cpp b/src/boost/libs/dll/test/cpp_test_library.cpp new file mode 100644 index 000000000..f32a3376a --- /dev/null +++ b/src/boost/libs/dll/test/cpp_test_library.cpp @@ -0,0 +1,203 @@ +// Copyright 2016 Klemens Morgenstern +// Copyright 2017-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include <boost/predef.h> + +#if (__cplusplus >= 201402L) || (BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(14,0,0)) + +#include <boost/dll/config.hpp> +#include <boost/variant.hpp> + +BOOST_SYMBOL_EXPORT extern int unscoped_var; +int unscoped_var = 42; + +BOOST_SYMBOL_EXPORT extern const double unscoped_c_var; +const double unscoped_c_var = 1.234; + + +namespace some_space { + +BOOST_SYMBOL_EXPORT extern double variable; +double variable = 0.2; +BOOST_SYMBOL_EXPORT const int & scoped_fun() +{ + static int x = 0xDEADBEEF; + return x; +} + +} + + +BOOST_SYMBOL_EXPORT void overloaded(const volatile int i) +{ + unscoped_var = i; +} + +BOOST_SYMBOL_EXPORT void overloaded(const double d) +{ + some_space::variable = d; +} + +BOOST_SYMBOL_EXPORT void use_variant(boost::variant<int, double> & v) +{ + v = 42; +} + +BOOST_SYMBOL_EXPORT void use_variant(boost::variant<double, int> & v) +{ + v = 3.124; +} + + + +namespace some_space +{ + +BOOST_SYMBOL_EXPORT extern int father_value; +int father_value = 12; + +struct BOOST_SYMBOL_EXPORT some_father +{ + some_father() { father_value = 24; }; + ~some_father() { father_value = 112; }; +}; + + + +struct BOOST_SYMBOL_EXPORT some_class : some_father +{ + static int value ; + static void set_value(const int &i); + + // static some_class* dummy(); + + virtual double func(double i, double j); + virtual int func(int i, int j); + int func(int i, int j) volatile; + double func(double i, double j) const volatile; + + int mem_val; + int get() const ; + void set(int i) ; + + some_class(); + some_class(some_class &&); + some_class(int i); + + some_class& operator=(some_class &&); + + + virtual ~some_class(); +}; + +some_class::some_class(some_class &&){} + + +some_class& some_class::operator=(some_class &&ref) {return ref;} + + +BOOST_SYMBOL_EXPORT extern std::size_t size_of_some_class; +std::size_t size_of_some_class = sizeof(some_space::some_class); + + +extern "C" BOOST_SYMBOL_EXPORT const volatile some_class* this_; +const volatile some_class * this_ = nullptr; + +int some_class::value = -1; + +void some_class::set_value(const int &i) {value = i;} + + +//some_class* some_class::dummy() {return new some_class();}//so it implements an allocating ctor. + +double some_class::func(double i, double j) {this_ = this; return i*j;} +int some_class::func(int i, int j) {this_ = this; return i+j;} +int some_class::func(int i, int j) volatile {this_ = this; return i-j;;} +double some_class::func(double i, double j) const volatile {this_ = this; return i/j;} + +int some_class::get() const {this_ = this; return mem_val;} +void some_class::set(int i) {this_ = this; mem_val = i;} + +some_class::some_class() { this_ = this; value = 23; mem_val = 123;} +some_class::some_class(int i) : mem_val(456) {this_ = this; value = i;} + +some_class::~some_class() +{ + value = 0; + this_ = this; +} + +} + +namespace space { + class BOOST_SYMBOL_EXPORT my_plugin; +} + +namespace testing { namespace space { + class BOOST_SYMBOL_EXPORT my_plugin { + public: + template<typename Arg> + BOOST_SYMBOL_EXPORT int Func() const; + template<typename Arg> + BOOST_SYMBOL_EXPORT int Func(); + template<typename Arg> + BOOST_SYMBOL_EXPORT int Func2(); + template<typename Arg> + BOOST_SYMBOL_EXPORT int AFunc(); + }; + + template<typename Arg> + BOOST_SYMBOL_EXPORT int my_plugin::Func() const { return 30; } + + template<typename Arg> + BOOST_SYMBOL_EXPORT int my_plugin::Func() { return 32; } + + template<typename Arg> + BOOST_SYMBOL_EXPORT int my_plugin::Func2() { return 33; } + + template<typename Arg> + BOOST_SYMBOL_EXPORT int my_plugin::AFunc() { return 31; } + + template BOOST_SYMBOL_EXPORT int my_plugin::Func<::space::my_plugin>(); + template BOOST_SYMBOL_EXPORT int my_plugin::Func2<::space::my_plugin>(); + template BOOST_SYMBOL_EXPORT int my_plugin::AFunc<::space::my_plugin>(); +}} + +namespace space { + class BOOST_SYMBOL_EXPORT my_plugin { + public: + template<typename Arg> + BOOST_SYMBOL_EXPORT int Func() const; + template<typename Arg> + BOOST_SYMBOL_EXPORT int Func(); + template<typename Arg> + BOOST_SYMBOL_EXPORT int Func2(); + template<typename Arg> + BOOST_SYMBOL_EXPORT int AFunc(); + }; + + template<typename Arg> + BOOST_SYMBOL_EXPORT int my_plugin::Func() const { return 40; } + + template<typename Arg> + BOOST_SYMBOL_EXPORT int my_plugin::Func() { return 42; } + + template<typename Arg> + BOOST_SYMBOL_EXPORT int my_plugin::Func2() { return 43; } + + template<typename Arg> + BOOST_SYMBOL_EXPORT int my_plugin::AFunc() { return 41; } + + template BOOST_SYMBOL_EXPORT int my_plugin::Func<::space::my_plugin>(); + template BOOST_SYMBOL_EXPORT int my_plugin::Func2<::space::my_plugin>(); + template BOOST_SYMBOL_EXPORT int my_plugin::AFunc<::space::my_plugin>(); +} + + +#endif diff --git a/src/boost/libs/dll/test/library_info_test.cpp b/src/boost/libs/dll/test/library_info_test.cpp new file mode 100644 index 000000000..e7808e961 --- /dev/null +++ b/src/boost/libs/dll/test/library_info_test.cpp @@ -0,0 +1,65 @@ +// Copyright 2011-2012 Renato Tegon Forti +// Copyright 2015-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +// MinGW related workaround +#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION +#include "../example/b2_workarounds.hpp" + +#include <boost/dll/library_info.hpp> +#include <boost/core/lightweight_test.hpp> +#include "../example/tutorial4/static_plugin.hpp" + +// Unit Tests + +#include <iterator> + +int main(int argc, char* argv[]) +{ + boost::dll::fs::path shared_library_path = b2_workarounds::first_lib_from_argv(argc, argv); + BOOST_TEST(shared_library_path.string().find("test_library") != std::string::npos); + + boost::dll::library_info lib_info(shared_library_path); + std::vector<std::string> sec = lib_info.sections(); + std::copy(sec.begin(), sec.end(), std::ostream_iterator<std::string>(std::cout, ", ")); + BOOST_TEST(std::find(sec.begin(), sec.end(), "boostdll") != sec.end()); + + + std::cout << "\n\n\n"; + std::vector<std::string> symb = lib_info.symbols(); + std::copy(symb.begin(), symb.end(), std::ostream_iterator<std::string>(std::cout, "\n")); + BOOST_TEST(std::find(symb.begin(), symb.end(), "const_integer_g") != symb.end()); + BOOST_TEST(std::find(symb.begin(), symb.end(), "say_hello") != symb.end()); + + symb = lib_info.symbols("boostdll"); + std::copy(symb.begin(), symb.end(), std::ostream_iterator<std::string>(std::cout, "\n")); + BOOST_TEST(std::find(symb.begin(), symb.end(), "const_integer_g_alias") != symb.end()); + BOOST_TEST(std::find(symb.begin(), symb.end(), "foo_variable") != symb.end()); + BOOST_TEST(std::find(symb.begin(), symb.end(), "const_integer_g") == symb.end()); + BOOST_TEST(std::find(symb.begin(), symb.end(), "say_hello") == symb.end()); + BOOST_TEST(lib_info.symbols(std::string("boostdll")) == symb); + + std::vector<std::string> empty = lib_info.symbols("empty"); + BOOST_TEST(empty.empty() == true); + + BOOST_TEST(lib_info.symbols("section_that_does_not_exist").empty()); + + // Self testing + std::cout << "Self: " << argv[0]; + boost::dll::library_info self_info(argv[0]); + + sec = self_info.sections(); + //std::copy(sec.begin(), sec.end(), std::ostream_iterator<std::string>(std::cout, ", ")); + BOOST_TEST(std::find(sec.begin(), sec.end(), "boostdll") != sec.end()); + + symb = self_info.symbols("boostdll"); + std::copy(symb.begin(), symb.end(), std::ostream_iterator<std::string>(std::cout, "\n")); + BOOST_TEST(std::find(symb.begin(), symb.end(), "create_plugin") != symb.end()); + + return boost::report_errors(); +} diff --git a/src/boost/libs/dll/test/link.hpp b/src/boost/libs/dll/test/link.hpp new file mode 100644 index 000000000..f84d8bd34 --- /dev/null +++ b/src/boost/libs/dll/test/link.hpp @@ -0,0 +1,21 @@ +// Copyright 2018-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see http://www.boost.org + + +#include <boost/predef.h> + +#if (__cplusplus >= 201402L) || (BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(14,0,0)) + +#include <boost/dll/smart_library.hpp> +#include <boost/dll/import_mangled.hpp> +#include <boost/dll/import_class.hpp> + +#endif + + +#include <boost/dll.hpp> diff --git a/src/boost/libs/dll/test/link1.cpp b/src/boost/libs/dll/test/link1.cpp new file mode 100644 index 000000000..639e827cf --- /dev/null +++ b/src/boost/libs/dll/test/link1.cpp @@ -0,0 +1,10 @@ +// Copyright 2018-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see http://www.boost.org + + +#include "link.hpp" diff --git a/src/boost/libs/dll/test/link2.cpp b/src/boost/libs/dll/test/link2.cpp new file mode 100644 index 000000000..670d39069 --- /dev/null +++ b/src/boost/libs/dll/test/link2.cpp @@ -0,0 +1,12 @@ +// Copyright 2018-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see http://www.boost.org + + +#include "link.hpp" + +int main() {} diff --git a/src/boost/libs/dll/test/section_name_too_big.cpp b/src/boost/libs/dll/test/section_name_too_big.cpp new file mode 100644 index 000000000..03db48f5c --- /dev/null +++ b/src/boost/libs/dll/test/section_name_too_big.cpp @@ -0,0 +1,17 @@ +// Copyright 2011-2012 Renato Tegon Forti +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION +#include <boost/dll/config.hpp> +#include <boost/dll/alias.hpp> + +int integer_g = 100; +BOOST_DLL_ALIAS_SECTIONED(integer_g, integer_g_aliased, "long_section_name") + diff --git a/src/boost/libs/dll/test/shared_library_concurrent_load_test.cpp b/src/boost/libs/dll/test/shared_library_concurrent_load_test.cpp new file mode 100644 index 000000000..e97926b7e --- /dev/null +++ b/src/boost/libs/dll/test/shared_library_concurrent_load_test.cpp @@ -0,0 +1,82 @@ +// Copyright 2015-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#ifdef BOOST_TRAVISCI_BUILD + +int main() { + return 0; +} + +#else // #ifdef BOOST_TRAVISCI_BUILD + +#include "../example/b2_workarounds.hpp" +#include <boost/dll.hpp> +#include <boost/filesystem/path.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/barrier.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/bind.hpp> +#include <cctype> +#include <vector> + +typedef std::vector<boost::dll::fs::path> paths_t; +const std::size_t thread_count = 4; +boost::barrier b(thread_count); + + +// Disgusting workarounds for b2 on Windows platform +inline paths_t generate_paths(int argc, char* argv[]) { + paths_t ret; + ret.reserve(argc - 1); + + for (int i = 1; i < argc; ++i) { + boost::dll::fs::path p = argv[i]; + if (b2_workarounds::is_shared_library(p)) { + ret.push_back(p); + } + } + + return ret; +} + +inline void load_unload(const paths_t& paths, std::size_t count) { + for (std::size_t j = 0; j < count; j += 2) { + for (std::size_t i = 0; i < paths.size(); ++i) { + boost::dll::shared_library lib(paths[i]); + BOOST_TEST(lib); + } + for (std::size_t i = 0; i < paths.size(); ++i) { + boost::dll::shared_library lib(paths[i]); + BOOST_TEST(lib.location() != ""); + } + + // Waiting for all threads to unload shared libraries + b.wait(); + } +} + + +int main(int argc, char* argv[]) { + BOOST_TEST(argc >= 3); + paths_t paths = generate_paths(argc, argv); + BOOST_TEST(!paths.empty()); + + std::cout << "Libraries:\n\t"; + std::copy(paths.begin(), paths.end(), std::ostream_iterator<boost::dll::fs::path>(std::cout, ", ")); + std::cout << std::endl; + + boost::thread_group threads; + for (std::size_t i = 0; i < thread_count; ++i) { + threads.create_thread(boost::bind(load_unload, paths, 1000)); + } + threads.join_all(); + + return boost::report_errors(); +} + +#endif // #ifdef BOOST_TRAVISCI_BUILD diff --git a/src/boost/libs/dll/test/shared_library_errors.cpp b/src/boost/libs/dll/test/shared_library_errors.cpp new file mode 100644 index 000000000..2f186fe1b --- /dev/null +++ b/src/boost/libs/dll/test/shared_library_errors.cpp @@ -0,0 +1,100 @@ +// Copyright 2011-2012 Renato Tegon Forti. +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include "../example/b2_workarounds.hpp" +#include <boost/dll/shared_library.hpp> +#include <boost/dll/library_info.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/function.hpp> + + +// Unit Tests +int main(int argc, char* argv[]) { + using namespace boost::dll; + + boost::dll::fs::path shared_library_path = b2_workarounds::first_lib_from_argv(argc, argv); + BOOST_TEST(shared_library_path.string().find("test_library") != std::string::npos); + BOOST_TEST(b2_workarounds::is_shared_library(shared_library_path)); + boost::dll::fs::path bad_path = shared_library_path / "directory_that_does_not_exist"; + + try { + shared_library lib(bad_path); + BOOST_TEST(false); + } catch (const boost::dll::fs::system_error& e) { + std::cout << e.what() << '\n'; + } + + try { + shared_library lib; + lib.get<int>("variable_or_function_that_does_not_exist"); + BOOST_TEST(false); + } catch (const boost::dll::fs::system_error& e) { + std::cout << e.what() << '\n'; + } + + try { + shared_library lib(""); + BOOST_TEST(false); + } catch (const boost::dll::fs::system_error& e) { + std::cout << e.what() << '\n'; + } + + try { + shared_library lib("\0\0"); + BOOST_TEST(false); + } catch (const boost::dll::fs::system_error& e) { + std::cout << e.what() << '\n'; + } + + try { + shared_library lib; + lib.location(); + BOOST_TEST(false); + } catch (const boost::dll::fs::system_error& e) { + std::cout << e.what() << '\n'; + } + + try { + shared_library lib; + lib.load("\0\0", load_mode::rtld_global); + BOOST_TEST(false); + } catch (const boost::dll::fs::system_error& e) { + std::cout << e.what() << '\n'; + } + + shared_library sl(shared_library_path); + try { + sl.get<int>("variable_or_function_that_does_not_exist"); + BOOST_TEST(false); + } catch (const boost::dll::fs::system_error& e) { + std::cout << e.what() << '\n'; + } + + try { + library_info lib("\0"); + BOOST_TEST(false); + } catch (const std::exception& e) { + std::cout << e.what() << '\n'; + } + + try { + std::string not_a_binary(argv[1]); + not_a_binary += "/not_a_binary"; + std::ofstream ofs(not_a_binary.c_str()); + ofs << "This is not a binary file, so library_info must report 'Unsupported binary format'"; + ofs.close(); + library_info lib(not_a_binary); + BOOST_TEST(false); + } catch (const std::exception& e) { + std::cout << e.what() << '\n'; + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/dll/test/shared_library_get_symbol_test.cpp b/src/boost/libs/dll/test/shared_library_get_symbol_test.cpp new file mode 100644 index 000000000..82e524d3d --- /dev/null +++ b/src/boost/libs/dll/test/shared_library_get_symbol_test.cpp @@ -0,0 +1,193 @@ +// Copyright 2011-2012 Renato Tegon Forti. +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include "../example/b2_workarounds.hpp" +#include <boost/dll.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/function.hpp> +#include <boost/fusion/container.hpp> +// lib functions + +typedef float (lib_version_func)(); +typedef void (say_hello_func) (); +typedef int (increment) (int); + +typedef boost::fusion::vector<std::vector<int>, std::vector<int>, std::vector<int>, const std::vector<int>*, std::vector<int>* > do_share_res_t; +typedef boost::shared_ptr<do_share_res_t> (do_share_t)( + std::vector<int> v1, + std::vector<int>& v2, + const std::vector<int>& v3, + const std::vector<int>* v4, + std::vector<int>* v5 + ); + +void refcountable_test(boost::dll::fs::path shared_library_path) { + using namespace boost::dll; + using namespace boost::fusion; + + std::vector<int> v(1000); + + { + boost::function<say_hello_func> sz2 + = import<say_hello_func>(shared_library_path, "say_hello"); + + sz2(); + sz2(); + sz2(); + } + + { + boost::function<std::size_t(const std::vector<int>&)> sz + = import_alias<std::size_t(const std::vector<int>&)>(shared_library_path, "foo_bar"); + BOOST_TEST(sz(v) == 1000); + } + + + { + boost::function<do_share_t> f; + + { + boost::function<do_share_t> f2 = import_alias<do_share_t>(shared_library_path, "do_share"); + f = f2; + } + + std::vector<int> v1(1, 1), v2(2, 2), v3(3, 3), v4(4, 4), v5(1000, 5); + boost::shared_ptr<do_share_res_t> res = f(v1, v2, v3, &v4, &v5); + + BOOST_TEST(at_c<0>(*res).size() == 1); BOOST_TEST(at_c<0>(*res).front() == 1); + BOOST_TEST(at_c<1>(*res).size() == 2); BOOST_TEST(at_c<1>(*res).front() == 2); + BOOST_TEST(at_c<2>(*res).size() == 3); BOOST_TEST(at_c<2>(*res).front() == 3); + BOOST_TEST(at_c<3>(*res)->size() == 4); BOOST_TEST(at_c<3>(*res)->front() == 4); + BOOST_TEST(at_c<4>(*res)->size() == 1000); BOOST_TEST(at_c<4>(*res)->front() == 5); + + BOOST_TEST(at_c<3>(*res) == &v4); + BOOST_TEST(at_c<4>(*res) == &v5); + BOOST_TEST(at_c<1>(*res).back() == 777); + BOOST_TEST(v5.back() == 9990); + } + + { + boost::shared_ptr<int> i = import<int>(shared_library_path, "integer_g"); + BOOST_TEST(*i == 100); + + boost::shared_ptr<int> i2; + i.swap(i2); + BOOST_TEST(*i2 == 100); + } + + { + boost::function<int&()> f = import_alias<int&()>(shared_library_path, "ref_returning_function"); + BOOST_TEST(f() == 0); + + f() = 10; + BOOST_TEST(f() == 10); + + boost::function<int&()> f1 = import_alias<int&()>(shared_library_path, "ref_returning_function"); + BOOST_TEST(f1() == 10); + + f1() += 10; + BOOST_TEST(f() == 20); + } + + { + boost::shared_ptr<const int> i = import<const int>(shared_library_path, "const_integer_g"); + BOOST_TEST(*i == 777); + + boost::shared_ptr<const int> i2 = i; + i.reset(); + BOOST_TEST(*i2 == 777); + } + + { + boost::shared_ptr<std::string> s = import_alias<std::string>(shared_library_path, "info"); + BOOST_TEST(*s == "I am a std::string from the test_library (Think of me as of 'Hello world'. Long 'Hello world')."); + + boost::shared_ptr<std::string> s2; + s.swap(s2); + BOOST_TEST(*s2 == "I am a std::string from the test_library (Think of me as of 'Hello world'. Long 'Hello world')."); + } +} + +// exe function +extern "C" int BOOST_SYMBOL_EXPORT exef() { + return 15; +} + +// Unit Tests +int main(int argc, char* argv[]) { + using namespace boost::dll; + + boost::dll::fs::path shared_library_path = b2_workarounds::first_lib_from_argv(argc, argv); + BOOST_TEST(shared_library_path.string().find("test_library") != std::string::npos); + BOOST_TEST(b2_workarounds::is_shared_library(shared_library_path)); + + refcountable_test(shared_library_path); + + shared_library sl(shared_library_path); + + BOOST_TEST(sl.get<int>("integer_g") == 100); + + sl.get<int>("integer_g") = 10; + BOOST_TEST(sl.get<int>("integer_g") == 10); + BOOST_TEST(sl.get<int>(std::string("integer_g")) == 10); + + BOOST_TEST(sl.get<say_hello_func>("say_hello")); + sl.get<say_hello_func>("say_hello")(); + + float ver = sl.get<lib_version_func>("lib_version")(); + BOOST_TEST(ver == 1.0); + + int n = sl.get<increment>("increment")(1); + BOOST_TEST(n == 2); + + BOOST_TEST(sl.get<const int>("const_integer_g") == 777); + + boost::function<int(int)> inc = sl.get<int(int)>("increment"); + BOOST_TEST(inc(1) == 2); + BOOST_TEST(inc(2) == 3); + BOOST_TEST(inc(3) == 4); + + // Checking that symbols are still available, after another load+unload of the library + { shared_library sl2(shared_library_path); } + + BOOST_TEST(inc(1) == 2); + BOOST_TEST(sl.get<int>("integer_g") == 10); + + + // Checking aliases + boost::function<std::size_t(const std::vector<int>&)> sz + = sl.get_alias<std::size_t(const std::vector<int>&)>("foo_bar"); + + std::vector<int> v(10); + BOOST_TEST(sz(v) == 10); + BOOST_TEST(sl.get_alias<std::size_t>("foo_variable") == 42); + + + sz = sl.get<std::size_t(*)(const std::vector<int>&)>("foo_bar"); + BOOST_TEST(sz(v) == 10); + BOOST_TEST(*sl.get<std::size_t*>("foo_variable") == 42); + + { // self + shared_library sl(program_location()); + int val = sl.get<int(void)>("exef")(); + BOOST_TEST(val == 15); + } + + int& reference_to_internal_integer = sl.get<int&>("reference_to_internal_integer"); + BOOST_TEST(reference_to_internal_integer == 0xFF0000); + +#ifndef BOOST_NO_RVALUE_REFERENCES + int&& rvalue_reference_to_internal_integer = sl.get<int&&>("rvalue_reference_to_internal_integer"); + BOOST_TEST(rvalue_reference_to_internal_integer == 0xFF0000); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/dll/test/shared_library_load_test.cpp b/src/boost/libs/dll/test/shared_library_load_test.cpp new file mode 100644 index 000000000..de7e619ee --- /dev/null +++ b/src/boost/libs/dll/test/shared_library_load_test.cpp @@ -0,0 +1,528 @@ +// Copyright 2011-2012 Renato Tegon Forti +// Copyright 2015-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include "../example/b2_workarounds.hpp" +#include <boost/dll.hpp> +#include <boost/core/lightweight_test.hpp> +// Unit Tests + +namespace boost { namespace dll { namespace fs { + +#ifdef BOOST_DLL_USE_STD_FS +using std::filesystem::remove; +using std::filesystem::copy; +#else +using boost::filesystem::remove; +using boost::filesystem::copy; +#endif + +}}} + +inline boost::dll::fs::path drop_version(const boost::dll::fs::path& lhs) { + boost::dll::fs::path ext = lhs.filename().extension(); + if (ext.native().size() > 1 && std::isdigit(ext.string()[1])) { + ext = lhs; + ext.replace_extension().replace_extension().replace_extension(); + return ext; + } + + return lhs; +} + +inline bool lib_path_equal(const boost::dll::fs::path& lhs, const boost::dll::fs::path& rhs) { + const bool res = (drop_version(lhs).filename() == drop_version(rhs).filename()); + if (!res) { + std::cerr << "lhs != rhs: " << lhs << " != " << rhs << '\n'; + } + return res; +} + +struct fs_copy_guard { + const boost::dll::fs::path actual_path_; + const bool same_; + + inline explicit fs_copy_guard(const boost::dll::fs::path& shared_library_path) + : actual_path_( drop_version(shared_library_path) ) + , same_(actual_path_ == shared_library_path) + { + if (!same_) { + boost::dll::fs::error_code ignore; + boost::dll::fs::remove(actual_path_, ignore); + boost::dll::fs::copy(shared_library_path, actual_path_, ignore); + } + } + + inline ~fs_copy_guard() { + if (!same_) { + boost::dll::fs::error_code ignore; + boost::dll::fs::remove(actual_path_, ignore); + } + } +}; + +// Disgusting workarounds for b2 on Windows platform +inline boost::dll::fs::path do_find_correct_libs_path(int argc, char* argv[], const char* lib_name) { + boost::dll::fs::path ret; + + for (int i = 1; i < argc; ++i) { + ret = argv[i]; + if (ret.string().find(lib_name) != std::string::npos && b2_workarounds::is_shared_library(ret)) { + return ret; + } + } + + return lib_name; +} + +int main(int argc, char* argv[]) +{ + using namespace boost::dll; + + BOOST_TEST(argc >= 3); + boost::dll::fs::path shared_library_path = do_find_correct_libs_path(argc, argv, "test_library"); + std::cout << "Library: " << shared_library_path; + + { + shared_library sl(shared_library_path); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + + shared_library sl2; + BOOST_TEST(!sl2.is_loaded()); + BOOST_TEST(!sl2); + + swap(sl, sl2); + BOOST_TEST(!sl.is_loaded()); + BOOST_TEST(!sl); + BOOST_TEST(sl2.is_loaded()); + BOOST_TEST(sl2); + + sl.assign(sl2); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(sl2.is_loaded()); + BOOST_TEST(sl2); + BOOST_TEST(sl2.location() == sl.location()); + + sl.assign(sl2); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(sl2.is_loaded()); + BOOST_TEST(sl2); + BOOST_TEST(sl2.location() == sl.location()); + + sl2.assign(sl); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(sl2.is_loaded()); + BOOST_TEST(sl2); + BOOST_TEST(sl2.location() == sl.location()); + + // Assigning an empty shared library + sl2.assign(shared_library()); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!sl2.is_loaded()); + BOOST_TEST(!sl2); + boost::dll::fs::error_code ec; + BOOST_TEST(sl2.location(ec) != sl.location()); + BOOST_TEST(ec); + } + + { + boost::dll::fs::error_code ec; + shared_library sl(shared_library_path, ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!ec); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path)); + BOOST_TEST(!ec); + + // Checking self assignment #1 + sl.assign(sl); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!ec); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path)); + + // Checking self assignment #2 + sl.assign(sl, ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!ec); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path)); + } + + { + shared_library sl; + BOOST_TEST(!sl.is_loaded()); + + sl.assign(sl); + BOOST_TEST(!sl); + + shared_library sl2(sl); + BOOST_TEST(!sl); + BOOST_TEST(!sl2); + + sl2.assign(sl); + BOOST_TEST(!sl); + BOOST_TEST(!sl2); + } + + { + shared_library sl; + sl.load(shared_library_path); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + } + + { + shared_library sl; + boost::dll::fs::error_code ec; + sl.load(shared_library_path, ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!ec); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + } + + { + shared_library sl(shared_library_path, load_mode::load_with_altered_search_path ); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + } + + { + boost::dll::fs::error_code ec; + shared_library sl(shared_library_path, load_mode::load_with_altered_search_path, ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!ec); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path)); + BOOST_TEST(!ec); + } + + { + boost::dll::fs::error_code ec; + shared_library sl(shared_library_path, load_mode::search_system_folders, ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!ec); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path)); + BOOST_TEST(!ec); + } + + { + try { +#if BOOST_OS_WINDOWS + boost::dll::shared_library("winmm.dll"); +#elif BOOST_OS_LINUX + boost::dll::shared_library("libdl.so"); +#endif + BOOST_TEST(false); + } catch (...) {} + } + + { + try { +#if BOOST_OS_WINDOWS + boost::dll::shared_library("winmm", load_mode::search_system_folders | load_mode::append_decorations); +#elif BOOST_OS_LINUX + boost::dll::shared_library("dl", boost::dll::load_mode::search_system_folders | load_mode::append_decorations); +#endif + } catch (...) { + BOOST_TEST(false); + } + } + + { + shared_library sl; + sl.load(shared_library_path, load_mode::load_with_altered_search_path); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + } + + { + shared_library sl; + boost::dll::fs::error_code ec; + sl.load(shared_library_path, load_mode::load_with_altered_search_path, ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + } + + { + shared_library sl(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + } + + { + shared_library sl(shared_library_path, load_mode::rtld_local); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + } + + { + shared_library sl(shared_library_path, load_mode::rtld_now); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + } + + { + fs_copy_guard guard(shared_library_path); + + boost::dll::fs::path platform_independent_path = guard.actual_path_; + platform_independent_path.replace_extension(); + if (platform_independent_path.filename().wstring().find(L"lib") == 0) { + platform_independent_path + = platform_independent_path.parent_path() / platform_independent_path.filename().wstring().substr(3); + } + std::cerr << "platform_independent_path: " << platform_independent_path << '\n'; + + shared_library sl(platform_independent_path, load_mode::append_decorations); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + + sl.unload(); + BOOST_TEST(!sl.is_loaded()); + BOOST_TEST(!sl); + } + + { + shared_library sl(shared_library_path, load_mode::rtld_now | load_mode::rtld_global | load_mode::load_with_altered_search_path); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + } + + { + boost::dll::fs::error_code ec; + shared_library sl(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global, ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!ec); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + } + + { + shared_library sl; + sl.load(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + } + + + { // Non-default flags with assignment + shared_library sl(shared_library_path, + load_mode::rtld_now | load_mode::rtld_global | load_mode::load_with_altered_search_path + +// `load_mode::rtld_deepbind` is incompatible with sanitizers: +// You are trying to dlopen a libtest_library.so shared library with RTLD_DEEPBIND flag which is incompatibe with sanitizer runtime +// (see https://github.com/google/sanitizers/issues/611 for details). +#ifndef BOOST_TRAVISCI_BUILD + | load_mode::rtld_deepbind +#endif + + ); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + + boost::dll::fs::error_code ec; + shared_library sl2(sl, ec); + BOOST_TEST(!ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(sl2.is_loaded()); + BOOST_TEST(sl2); + BOOST_TEST(sl2.location() == sl.location()); + + shared_library sl3(sl); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(sl3.is_loaded()); + BOOST_TEST(sl3); + + shared_library sl4; + sl4.assign(sl, ec); + BOOST_TEST(!ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(sl4.is_loaded()); + BOOST_TEST(sl4); + } + + { // Non-default flags with assignment and error_code + boost::dll::fs::error_code ec; + shared_library sl(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global, ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!ec); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + + shared_library sl2(sl, ec); + BOOST_TEST(!ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(sl2.is_loaded()); + BOOST_TEST(sl2); + BOOST_TEST(sl2.location() == sl.location()); + + shared_library sl3(sl); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(sl3.is_loaded()); + BOOST_TEST(sl3); + BOOST_TEST(sl3.location() == sl.location()); + } + + { // self_load + shared_library sl(program_location()); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + std::cout << "\nProgram location: " << program_location(); + std::cout << "\nLibrary location: " << sl.location(); + BOOST_TEST( boost::dll::fs::equivalent(sl.location(), program_location()) ); + + boost::dll::fs::error_code ec; + shared_library sl2(program_location()); + BOOST_TEST(sl2.is_loaded()); + BOOST_TEST( boost::dll::fs::equivalent(sl2.location(), program_location()) ); + BOOST_TEST(sl2); + BOOST_TEST(!ec); + + BOOST_TEST(sl == sl2); + BOOST_TEST(!(sl < sl2 || sl2 <sl)); + BOOST_TEST(!(sl != sl2)); + + sl.load(shared_library_path); + BOOST_TEST(sl != sl2); + BOOST_TEST(sl < sl2 || sl2 <sl); + BOOST_TEST(!(sl == sl2)); + + sl.unload(); + BOOST_TEST(!sl); + BOOST_TEST(sl != sl2); + BOOST_TEST(sl < sl2 || sl2 <sl); + BOOST_TEST(!(sl == sl2)); + + sl2.unload(); + BOOST_TEST(!sl2); + BOOST_TEST(sl == sl2); + BOOST_TEST(!(sl < sl2 || sl2 <sl)); + BOOST_TEST(!(sl != sl2)); + + // assigning self + sl.load(program_location()); + sl2 = sl; + BOOST_TEST(sl == sl2); + BOOST_TEST(sl.location() == sl2.location()); + } + + { + shared_library sl; + boost::dll::fs::error_code ec; + sl.load(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global, ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!ec); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + + sl.load(program_location()); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + + sl.load(program_location()); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!ec); + } + + { // self_load + shared_library sl; + boost::dll::fs::error_code ec; + sl.load(program_location()); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(!ec); + } + + { // unload + shared_library sl(shared_library_path); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); + sl.unload(); + BOOST_TEST(!sl.is_loaded()); + BOOST_TEST(!sl); + } + + + { // error_code load calls test + boost::dll::fs::error_code ec; + shared_library sl(shared_library_path / "dir_that_does_not_exist", ec); + BOOST_TEST(ec); + BOOST_TEST(!sl.is_loaded()); + BOOST_TEST(!sl); + + boost::dll::fs::path bad_path(shared_library_path); + bad_path += ".1.1.1.1.1.1"; + sl.load(bad_path, ec); + BOOST_TEST(ec); + BOOST_TEST(!sl.is_loaded()); + BOOST_TEST(!sl); + + sl.load(shared_library_path, ec); + BOOST_TEST(!ec); + BOOST_TEST(sl.is_loaded()); + BOOST_TEST(sl); + + shared_library sl2(bad_path, ec); + BOOST_TEST(ec); + BOOST_TEST(!sl2.is_loaded()); + BOOST_TEST(!sl2); + + shared_library sl3(shared_library_path, ec); + BOOST_TEST(!ec); + BOOST_TEST(sl3.is_loaded()); + BOOST_TEST(sl3); + + sl.load("", ec); + BOOST_TEST(ec); + BOOST_TEST(!sl.is_loaded()); + BOOST_TEST(!sl); + } + + + shared_library_path = do_find_correct_libs_path(argc, argv, "library1"); + fs_copy_guard guard(shared_library_path); + shared_library starts_with_lib( + boost::dll::fs::path(guard.actual_path_).replace_extension(), + load_mode::append_decorations + ); + + starts_with_lib.load( + boost::dll::fs::path(guard.actual_path_).replace_extension(), + load_mode::append_decorations + ); + + return boost::report_errors(); +} diff --git a/src/boost/libs/dll/test/shared_library_search_symbol_test.cpp b/src/boost/libs/dll/test/shared_library_search_symbol_test.cpp new file mode 100644 index 000000000..cf1dc66fc --- /dev/null +++ b/src/boost/libs/dll/test/shared_library_search_symbol_test.cpp @@ -0,0 +1,49 @@ +// Copyright 2011-2012 Renato Tegon Forti +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include "../example/b2_workarounds.hpp" +#include <boost/dll.hpp> +#include <boost/core/lightweight_test.hpp> + +// Unit Tests + +extern "C" void BOOST_SYMBOL_EXPORT exef() { +} + +int main(int argc, char* argv[]) +{ + using namespace boost::dll; + + boost::dll::fs::path shared_library_path = b2_workarounds::first_lib_from_argv(argc, argv); + BOOST_TEST(shared_library_path.string().find("test_library") != std::string::npos); + BOOST_TEST(b2_workarounds::is_shared_library(shared_library_path)); + std::cout << "Library: " << shared_library_path; + + { + shared_library sl(shared_library_path); + BOOST_TEST(sl.has("say_hello")); + BOOST_TEST(sl.has("lib_version")); + BOOST_TEST(sl.has("integer_g")); + BOOST_TEST(sl.has(std::string("integer_g"))); + BOOST_TEST(!sl.has("i_do_not_exist")); + BOOST_TEST(!sl.has(std::string("i_do_not_exist"))); + } + + { + shared_library sl(program_location()); + BOOST_TEST(sl.has("exef")); + BOOST_TEST(!sl.has("i_do_not_exist")); + } + + + exef(); // Make sure that this function still callable in traditional way + return boost::report_errors(); +} + diff --git a/src/boost/libs/dll/test/structures_tests.cpp b/src/boost/libs/dll/test/structures_tests.cpp new file mode 100644 index 000000000..1598dc735 --- /dev/null +++ b/src/boost/libs/dll/test/structures_tests.cpp @@ -0,0 +1,345 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include <boost/dll/detail/elf_info.hpp> +#include <boost/dll/detail/pe_info.hpp> +#include <boost/dll/detail/macho_info.hpp> +#include <boost/static_assert.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/predef/os.h> + +#if BOOST_OS_WINDOWS +# include <windows.h> +#elif BOOST_OS_MACOS || BOOST_OS_IOS +# include <mach-o/loader.h> +# include <mach-o/nlist.h> +#elif BOOST_OS_QNX +// QNX's copy of <elf.h> and <link.h> reside in sys folder +# include <sys/elf.h> +#else + #include <elf.h> +#endif + +namespace dd = boost::dll::detail; + +template <class T1, class T2> +inline std::size_t get_offset(const T1& v1, const T2& v2) { + const unsigned char* p1 = reinterpret_cast<const unsigned char*>(&v1); + const unsigned char* p2 = reinterpret_cast<const unsigned char*>(&v2); + + if (p1 < p2) { + return static_cast<std::size_t>(p2 - p1); + } + + return static_cast<std::size_t>(p1 - p2); +} + +#define CHECK_FIELD(Field) \ + BOOST_STATIC_ASSERT(sizeof(v1.Field) == sizeof(v2.Field)); \ + BOOST_TEST(get_offset(v1, v1.Field) == get_offset(v2, v2.Field)) \ + /**/ + + +// ELF structures +template <class T1, class T2> +void elf_header_checks(const T1& v1, const T2& v2) { + BOOST_STATIC_ASSERT(sizeof(T1) == sizeof(T2)); + + CHECK_FIELD(e_ident); + CHECK_FIELD(e_type); + CHECK_FIELD(e_machine); + CHECK_FIELD(e_version); + CHECK_FIELD(e_entry); + CHECK_FIELD(e_phoff); + CHECK_FIELD(e_shoff); + CHECK_FIELD(e_flags); + CHECK_FIELD(e_ehsize); + CHECK_FIELD(e_phentsize); + CHECK_FIELD(e_phnum); + CHECK_FIELD(e_shentsize); + CHECK_FIELD(e_shnum); + CHECK_FIELD(e_shstrndx); +} + +template <class T1, class T2> +void elf_sheader_checks(const T1& v1, const T2& v2) { + BOOST_STATIC_ASSERT(sizeof(T1) == sizeof(T2)); + + CHECK_FIELD(sh_name); + CHECK_FIELD(sh_type); + CHECK_FIELD(sh_flags); + CHECK_FIELD(sh_addr); + CHECK_FIELD(sh_offset); + CHECK_FIELD(sh_size); + CHECK_FIELD(sh_link); + CHECK_FIELD(sh_info); + CHECK_FIELD(sh_addralign); + CHECK_FIELD(sh_entsize); +} + +template <class T1, class T2> +void elf_sym_header_checks(const T1& v1, const T2& v2) { + BOOST_STATIC_ASSERT(sizeof(T1) == sizeof(T2)); + + CHECK_FIELD(st_name); + CHECK_FIELD(st_value); + CHECK_FIELD(st_size); + CHECK_FIELD(st_info); + CHECK_FIELD(st_other); + CHECK_FIELD(st_shndx); +} + + +// PE structures +template <class T> +void generic_header_check(const T& v1, const dd::IMAGE_DOS_HEADER_& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(e_magic); + CHECK_FIELD(e_cblp); + CHECK_FIELD(e_cp); + CHECK_FIELD(e_crlc); + CHECK_FIELD(e_cparhdr); + CHECK_FIELD(e_minalloc); + CHECK_FIELD(e_maxalloc); + CHECK_FIELD(e_ss); + CHECK_FIELD(e_sp); + CHECK_FIELD(e_csum); + CHECK_FIELD(e_ip); + CHECK_FIELD(e_cs); + CHECK_FIELD(e_lfarlc); + CHECK_FIELD(e_ovno); + CHECK_FIELD(e_res); + CHECK_FIELD(e_oemid); + CHECK_FIELD(e_oeminfo); + CHECK_FIELD(e_res2); + CHECK_FIELD(e_lfanew); +} + +template <class T> +void generic_header_check(const T& v1, const dd::IMAGE_FILE_HEADER_& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(Machine); + CHECK_FIELD(NumberOfSections); + CHECK_FIELD(TimeDateStamp); + CHECK_FIELD(PointerToSymbolTable); + CHECK_FIELD(NumberOfSymbols); + CHECK_FIELD(SizeOfOptionalHeader); + CHECK_FIELD(Characteristics); +} + +template <class T> +void generic_header_check(const T& v1, const dd::IMAGE_DATA_DIRECTORY_& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(VirtualAddress); + CHECK_FIELD(Size); +} + +template <class T> +void generic_header_check(const T& v1, const dd::IMAGE_EXPORT_DIRECTORY_& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(Characteristics); + CHECK_FIELD(TimeDateStamp); + CHECK_FIELD(MajorVersion); + CHECK_FIELD(MinorVersion); + CHECK_FIELD(Name); + CHECK_FIELD(Base); + CHECK_FIELD(NumberOfFunctions); + CHECK_FIELD(NumberOfNames); + CHECK_FIELD(AddressOfFunctions); + CHECK_FIELD(AddressOfNames); + CHECK_FIELD(AddressOfNameOrdinals); +} + + +template <class T> +void generic_header_check(const T& v1, const dd::IMAGE_SECTION_HEADER_& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(Name); + CHECK_FIELD(VirtualAddress); + CHECK_FIELD(SizeOfRawData); + CHECK_FIELD(PointerToRawData); + CHECK_FIELD(PointerToRelocations); + CHECK_FIELD(PointerToLinenumbers); + CHECK_FIELD(NumberOfRelocations); + CHECK_FIELD(NumberOfLinenumbers); + CHECK_FIELD(Characteristics); +} + +template <class T, class AddrT> +void generic_header_check(const T& v1, const dd::IMAGE_OPTIONAL_HEADER_template<AddrT>& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(Magic); + CHECK_FIELD(MajorLinkerVersion); + CHECK_FIELD(MinorLinkerVersion); + CHECK_FIELD(SizeOfCode); + CHECK_FIELD(SizeOfInitializedData); + CHECK_FIELD(SizeOfUninitializedData); + CHECK_FIELD(AddressOfEntryPoint); + CHECK_FIELD(ImageBase); + CHECK_FIELD(SectionAlignment); + CHECK_FIELD(FileAlignment); + CHECK_FIELD(MajorOperatingSystemVersion); + CHECK_FIELD(MinorOperatingSystemVersion); + CHECK_FIELD(MajorImageVersion); + CHECK_FIELD(MinorImageVersion); + CHECK_FIELD(MajorSubsystemVersion); + CHECK_FIELD(MinorSubsystemVersion); + CHECK_FIELD(Win32VersionValue); + CHECK_FIELD(SizeOfImage); + CHECK_FIELD(SizeOfHeaders); + CHECK_FIELD(CheckSum); + CHECK_FIELD(Subsystem); + CHECK_FIELD(DllCharacteristics); + CHECK_FIELD(SizeOfStackReserve); + CHECK_FIELD(SizeOfStackCommit); + CHECK_FIELD(SizeOfHeapReserve); + CHECK_FIELD(SizeOfHeapCommit); + CHECK_FIELD(LoaderFlags); + CHECK_FIELD(NumberOfRvaAndSizes); + CHECK_FIELD(DataDirectory); +} + +template <class T, class AddrT> +void generic_header_check(const T& v1, const dd::IMAGE_NT_HEADERS_template<AddrT>& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(Signature); + CHECK_FIELD(FileHeader); + CHECK_FIELD(OptionalHeader); +} +template <class T, class AddrT> +void generic_header_check(const T& v1, const dd::mach_header_template<AddrT>& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(magic); + CHECK_FIELD(cputype); + CHECK_FIELD(cpusubtype); + CHECK_FIELD(filetype); + CHECK_FIELD(ncmds); + CHECK_FIELD(sizeofcmds); + //CHECK_FIELD(flags); +} + +template <class T, class AddrT> +void generic_header_check(const T& v1, const dd::segment_command_template<AddrT>& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(cmd); + CHECK_FIELD(cmdsize); + CHECK_FIELD(segname); + CHECK_FIELD(vmaddr); + CHECK_FIELD(vmsize); + CHECK_FIELD(fileoff); + CHECK_FIELD(filesize); + CHECK_FIELD(maxprot); + CHECK_FIELD(initprot); + CHECK_FIELD(nsects); + CHECK_FIELD(flags); +} + +template <class T, class AddrT> +void generic_header_check(const T& v1, const dd::section_template<AddrT>& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(sectname); + CHECK_FIELD(segname); + CHECK_FIELD(addr); + CHECK_FIELD(size); + CHECK_FIELD(offset); + CHECK_FIELD(align); + CHECK_FIELD(reloff); + CHECK_FIELD(nreloc); + CHECK_FIELD(flags); + //CHECK_FIELD(reserved vs reserveed1&reserved2); +} + +template <class T> +void generic_header_check(const T& v1, const dd::symtab_command_& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(cmd); + CHECK_FIELD(cmdsize); + CHECK_FIELD(symoff); + CHECK_FIELD(nsyms); + CHECK_FIELD(stroff); + CHECK_FIELD(strsize); +} + +template <class T, class AddrT> +void generic_header_check(const T& v1, const dd::nlist_template<AddrT>& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + //CHECK_FIELD(n_strx); + CHECK_FIELD(n_type); + CHECK_FIELD(n_sect); + CHECK_FIELD(n_desc); + CHECK_FIELD(n_value); +} + +template <class T> +void generic_header_check(const T& v1, const dd::load_command_& v2) { + BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2)); + + CHECK_FIELD(cmd); + CHECK_FIELD(cmdsize); +} + + + +// Unit Tests +int main(int /*argc*/, char* /*argv*/[]) { + +#if BOOST_OS_WINDOWS + generic_header_check(::IMAGE_DOS_HEADER(), dd::IMAGE_DOS_HEADER_()); + generic_header_check(::IMAGE_FILE_HEADER(), dd::IMAGE_FILE_HEADER_()); + generic_header_check(::IMAGE_DATA_DIRECTORY(), dd::IMAGE_DATA_DIRECTORY_()); + generic_header_check(::IMAGE_EXPORT_DIRECTORY(), dd::IMAGE_EXPORT_DIRECTORY_()); + generic_header_check(::IMAGE_SECTION_HEADER(), dd::IMAGE_SECTION_HEADER_()); + generic_header_check(::IMAGE_OPTIONAL_HEADER32(), dd::IMAGE_OPTIONAL_HEADER32_()); + generic_header_check(::IMAGE_OPTIONAL_HEADER64(), dd::IMAGE_OPTIONAL_HEADER64_()); + generic_header_check(::IMAGE_NT_HEADERS32(), dd::IMAGE_NT_HEADERS32_()); + generic_header_check(::IMAGE_NT_HEADERS64(), dd::IMAGE_NT_HEADERS64_()); +#elif BOOST_OS_MACOS || BOOST_OS_IOS + generic_header_check(::mach_header(), dd::mach_header_32_()); + generic_header_check(::mach_header_64(), dd::mach_header_64_()); + + generic_header_check(::segment_command(), dd::segment_command_32_()); + generic_header_check(::segment_command_64(), dd::segment_command_64_()); + + generic_header_check(::section(), dd::section_32_()); + generic_header_check(::section_64(), dd::section_64_()); + + generic_header_check(::load_command(), dd::load_command_()); + generic_header_check(::symtab_command(), dd::symtab_command_()); + + struct ::nlist nl32_var; + generic_header_check(nl32_var, dd::nlist_32_()); + struct ::nlist_64 nl64_var; + generic_header_check(nl64_var, dd::nlist_64_()); + +#else + elf_header_checks(::Elf32_Ehdr(), dd::Elf32_Ehdr_()); + elf_header_checks(::Elf64_Ehdr(), dd::Elf64_Ehdr_()); + + elf_sheader_checks(::Elf32_Shdr(), dd::Elf32_Shdr_()); + elf_sheader_checks(::Elf64_Shdr(), dd::Elf64_Shdr_()); + + elf_sym_header_checks(::Elf32_Sym(), dd::Elf32_Sym_()); + elf_sym_header_checks(::Elf64_Sym(), dd::Elf64_Sym_()); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/dll/test/symbol_runtime_info_test.cpp b/src/boost/libs/dll/test/symbol_runtime_info_test.cpp new file mode 100644 index 000000000..bfeb69bf6 --- /dev/null +++ b/src/boost/libs/dll/test/symbol_runtime_info_test.cpp @@ -0,0 +1,231 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include "../example/b2_workarounds.hpp" +#include <boost/dll.hpp> +#include <boost/dll/runtime_symbol_info.hpp> +#include <boost/filesystem/operations.hpp> + +#include <boost/core/lightweight_test.hpp> + +#include <boost/predef/os.h> + + +#include <cmath> +#include <exception> // std::set_terminate +#include <signal.h> // ::signal + +// Makes global error variables dirty. Useful for preventing issues like https://github.com/boostorg/dll/issues/16 +void make_error_code_dirty() { + using namespace std; + (void)log(-1.0); + +#if BOOST_OS_WINDOWS + boost::winapi::WCHAR_ path_hldr[10]; + int some_invalid_value_for_handle = 0xFF004242; + boost::winapi::HMODULE_ some_invalid_handle; + memcpy(&some_invalid_handle, &some_invalid_value_for_handle, sizeof(some_invalid_value_for_handle)); + boost::winapi::GetModuleFileNameW(some_invalid_handle, path_hldr, 10); +#endif +} + + + +// lib functions + +typedef float (lib_version_func)(); +typedef void (say_hello_func) (); +typedef int (increment) (int); + +// exe function +extern "C" int BOOST_SYMBOL_EXPORT exef() { + return 15; +} + + +extern "C" void BOOST_SYMBOL_EXPORT my_terminate_handler() { + std::abort(); +} + +extern "C" void BOOST_SYMBOL_EXPORT my_signal_handler(int) { + std::abort(); +} + +void internal_function() {} +int internal_variable = 1; + +// Unit Tests +int main(int argc, char* argv[]) { + using namespace boost::dll; + + boost::dll::fs::path shared_library_path = b2_workarounds::first_lib_from_argv(argc, argv); + BOOST_TEST(shared_library_path.string().find("test_library") != std::string::npos); + + make_error_code_dirty(); + + shared_library lib(shared_library_path); + + std::cout << std::endl; + std::cout << "shared_library: " << shared_library_path << std::endl; + std::cout << "symbol_location: " << symbol_location(lib.get<int>("integer_g")) << std::endl; + std::cout << "lib.location(): " << lib.location() << std::endl; + BOOST_TEST( + symbol_location(lib.get<int>("integer_g")) == lib.location() + ); + + make_error_code_dirty(); + + BOOST_TEST( + symbol_location(lib.get<say_hello_func>("say_hello")) == lib.location() + ); + + BOOST_TEST( + symbol_location(lib.get<lib_version_func>("lib_version")) == lib.location() + ); + + make_error_code_dirty(); + + BOOST_TEST( + symbol_location(lib.get<const int>("const_integer_g")) == lib.location() + ); + + // Checking that symbols are still available, after another load+unload of the library + { shared_library sl2(shared_library_path); } + + BOOST_TEST( + symbol_location(lib.get<int>("integer_g")) == lib.location() + ); + + + make_error_code_dirty(); + + // Checking aliases + BOOST_TEST( + symbol_location(lib.get<std::size_t(*)(const std::vector<int>&)>("foo_bar")) == lib.location() + ); + BOOST_TEST( + symbol_location(lib.get_alias<std::size_t(const std::vector<int>&)>("foo_bar")) == lib.location() + ); + + + BOOST_TEST( + symbol_location(lib.get<std::size_t*>("foo_variable")) == lib.location() + ); + BOOST_TEST( + symbol_location(lib.get_alias<std::size_t>("foo_variable")) == lib.location() + ); + + { // self + + make_error_code_dirty(); + + shared_library sl(program_location()); + + make_error_code_dirty(); + + BOOST_TEST( + (boost::dll::fs::equivalent(symbol_location(sl.get<int(void)>("exef")), argv[0])) + ); + } + + { // self with error_code + boost::dll::fs::error_code ec; + shared_library sl(program_location(ec)); + BOOST_TEST(!ec); + + BOOST_TEST( + (boost::dll::fs::equivalent(symbol_location(sl.get<int(void)>("exef"), ec), argv[0])) + ); + BOOST_TEST(!ec); + + symbol_location(&sl.get<int(void)>("exef"), ec); + BOOST_TEST(ec); + } + + std::cout << "\ninternal_function: " << symbol_location(internal_function); + std::cout << "\nargv[0] : " << boost::filesystem::absolute(argv[0]); + BOOST_TEST( + (boost::dll::fs::equivalent(symbol_location(internal_function), argv[0])) + ); + + BOOST_TEST( + (boost::dll::fs::equivalent(symbol_location(internal_variable), argv[0])) + ); + + make_error_code_dirty(); + + BOOST_TEST( + (boost::dll::fs::equivalent(this_line_location(), argv[0])) + ); + + { // this_line_location with error_code + boost::dll::fs::error_code ec; + make_error_code_dirty(); + BOOST_TEST( + (boost::dll::fs::equivalent(this_line_location(ec), argv[0])) + ); + BOOST_TEST(!ec); + } + + BOOST_TEST( + lib.get_alias<boost::dll::fs::path()>("module_location_from_itself")() == lib.location() + ); + + // Checking docs content + std::cout << "\nsymbol_location(std::cerr); // " << symbol_location(std::cerr); + std::cout << "\nsymbol_location(std::puts); // " << symbol_location(std::puts); + + std::set_terminate(&my_terminate_handler); + BOOST_TEST((boost::dll::fs::equivalent( + symbol_location_ptr(std::set_terminate(0)), + argv[0] + ))); + + { + boost::dll::fs::error_code ec; + boost::dll::fs::path p = symbol_location_ptr(std::set_terminate(0), ec); + BOOST_TEST(ec || !p.empty()); + } + + { + boost::dll::fs::error_code ec; + symbol_location(std::set_terminate(0), ec), + BOOST_TEST(ec); + } + + { + std::set_terminate(&my_terminate_handler); + boost::dll::fs::error_code ec; + make_error_code_dirty(); + symbol_location(std::set_terminate(0), ec), + BOOST_TEST(ec); + } + + { + boost::dll::fs::error_code ec; + ::signal(SIGSEGV, &my_signal_handler); + boost::dll::fs::path p = symbol_location_ptr(::signal(SIGSEGV, SIG_DFL), ec); + BOOST_TEST((boost::dll::fs::equivalent( + p, + argv[0] + )) || ec); + } + + { + ::signal(SIGSEGV, &my_signal_handler); + boost::dll::fs::error_code ec; + make_error_code_dirty(); + symbol_location(::signal(SIGSEGV, SIG_DFL), ec); + BOOST_TEST(ec); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/dll/test/template_method_linux_test.cpp b/src/boost/libs/dll/test/template_method_linux_test.cpp new file mode 100644 index 000000000..cb4969609 --- /dev/null +++ b/src/boost/libs/dll/test/template_method_linux_test.cpp @@ -0,0 +1,67 @@ +// Copyright 2019 Ramil Gauss. +// Copyright 2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/predef.h> +#if (__cplusplus >= 201402L) || (BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(14,0,0)) + +#include <boost/dll/smart_library.hpp> +#include <boost/dll/import_mangled.hpp> +#include <boost/dll/import_class.hpp> + +#include <iostream> +#include <string> + +#include "../example/b2_workarounds.hpp" +#include <boost/core/lightweight_test.hpp> + + +namespace space { + class BOOST_SYMBOL_EXPORT my_plugin { + public: + template <typename Arg> + BOOST_SYMBOL_EXPORT int Func(); // defined in cpp_test_library.cpp + }; +} + +int main(int argc, char** argv) { + unsigned matches_found = 0; + boost::dll::fs::path lib_path = b2_workarounds::first_lib_from_argv(argc, argv); + boost::dll::experimental::smart_library lib(lib_path); + + auto storage = lib.symbol_storage().get_storage(); + for (auto& s : storage) { + auto& demangled = s.demangled; + BOOST_TEST(demangled.data()); + + auto beginFound = demangled.find("Func<"); + if (beginFound == std::string::npos) + continue; + + auto endFound = demangled.find("("); + if (endFound == std::string::npos) + continue; + + // Usually "Func<space::my_plugin>" on Linux, "Func<class space::my_plugin>" on Windows. + auto funcName = demangled.substr(beginFound, endFound - beginFound); + std::cout << "Function name: " << funcName.data() << std::endl; + auto typeIndexFunc = boost::dll::experimental::import_mangled<space::my_plugin, int()>(lib, funcName); + + space::my_plugin cl; + BOOST_TEST_EQ(typeIndexFunc(&cl), 42); + + ++matches_found; + break; + } + BOOST_TEST_EQ(matches_found, 1); + + return boost::report_errors(); +} + + +#else +int main() {} +#endif diff --git a/src/boost/libs/dll/test/test_library.cpp b/src/boost/libs/dll/test/test_library.cpp new file mode 100644 index 000000000..fee07c629 --- /dev/null +++ b/src/boost/libs/dll/test/test_library.cpp @@ -0,0 +1,115 @@ +// Copyright 2011-2012 Renato Tegon Forti +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright 2015-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +// MinGW related workaround +#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION + +#include <boost/dll/config.hpp> +#include <boost/dll/alias.hpp> +#include <iostream> +#include <vector> + +#include <boost/shared_ptr.hpp> +#include <boost/make_shared.hpp> +#include <boost/fusion/container.hpp> + +#define LIBRARY_API BOOST_SYMBOL_EXPORT + +extern "C" void LIBRARY_API say_hello(void); +extern "C" float LIBRARY_API lib_version(void); +extern "C" int LIBRARY_API increment(int); + +extern "C" int LIBRARY_API integer_g; +extern "C" const int LIBRARY_API const_integer_g = 777; + +namespace foo { + std::size_t bar(const std::vector<int>& v) { + return v.size(); + } + + std::size_t variable = 42; +} + + + +// Make sure that aliases have no problems with memory allocations and different types of input parameters +namespace namespace1 { namespace namespace2 { namespace namespace3 { + typedef + boost::fusion::vector<std::vector<int>, std::vector<int>, std::vector<int>, const std::vector<int>*, std::vector<int>* > + do_share_res_t; + + boost::shared_ptr<do_share_res_t> do_share( + std::vector<int> v1, + std::vector<int>& v2, + const std::vector<int>& v3, + const std::vector<int>* v4, + std::vector<int>* v5 + ) + { + v2.back() = 777; + v5->back() = 9990; + return boost::make_shared<do_share_res_t>(v1, v2, v3, v4, v5); + } + + std::string info("I am a std::string from the test_library (Think of me as of 'Hello world'. Long 'Hello world')."); + + int& ref_returning_function() { + static int i = 0; + return i; + } +}}} + + + +BOOST_DLL_ALIAS(foo::bar, foo_bar) +BOOST_DLL_ALIAS(foo::variable, foo_variable) +BOOST_DLL_ALIAS(namespace1::namespace2::namespace3::do_share, do_share) +BOOST_DLL_ALIAS(namespace1::namespace2::namespace3::info, info) +BOOST_DLL_ALIAS(const_integer_g, const_integer_g_alias) +BOOST_DLL_ALIAS(namespace1::namespace2::namespace3::ref_returning_function, ref_returning_function) + + + +int integer_g = 100; + +void say_hello(void) +{ + std::cout << "Hello, Boost.Application!" << std::endl; +} + +float lib_version(void) +{ + return 1.0; +} + +int increment(int n) +{ + return ++n; +} + +#include <boost/dll/runtime_symbol_info.hpp> + +boost::dll::fs::path this_module_location_from_itself() { + return boost::dll::this_line_location(); +} + +BOOST_DLL_ALIAS(this_module_location_from_itself, module_location_from_itself) + + + +int internal_integer_i = 0xFF0000; +extern "C" LIBRARY_API int& reference_to_internal_integer; +int& reference_to_internal_integer = internal_integer_i; + +#ifndef BOOST_NO_RVALUE_REFERENCES +extern "C" LIBRARY_API int&& rvalue_reference_to_internal_integer; +int&& rvalue_reference_to_internal_integer = static_cast<int&&>(internal_integer_i); +#endif + |