1// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
2// Copyright Antony Polukhin, 2015-2024.
3//
4// Distributed under the Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt
6// or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8// MinGW related workaround
9#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION
10
11#include "../b2_workarounds.hpp"
12#include "../tutorial4/static_plugin.hpp"
13#include <boost/dll/runtime_symbol_info.hpp> // for program_location()
14#include <boost/dll/shared_library.hpp>
15#include <boost/make_shared.hpp>
16#include <boost/container/map.hpp>
17#include <boost/filesystem.hpp>
18#include <iostream>
19
20//[plugcpp_plugins_collector_def
21namespace dll = boost::dll;
22
23class plugins_collector {
24 // Name => plugin
25 typedef boost::container::map<std::string, dll::shared_library> plugins_t;
26
27 boost::dll::fs::path plugins_directory_;
28 plugins_t plugins_;
29
30 // loads all plugins in plugins_directory_
31 void load_all();
32
33 // Gets `my_plugin_api` instance using "create_plugin" or "plugin" imports,
34 // stores plugin with its name in the `plugins_` map.
35 void insert_plugin(BOOST_RV_REF(dll::shared_library) lib);
36
37public:
38 plugins_collector(const boost::dll::fs::path& plugins_directory)
39 : plugins_directory_(plugins_directory)
40 {
41 load_all();
42 }
43
44 void print_plugins() const;
45
46 std::size_t count() const;
47 // ...
48};
49//]
50
51
52//[plugcpp_plugins_collector_load_all
53void plugins_collector::load_all() {
54 namespace fs = ::boost::dll::fs;
55 typedef fs::path::string_type string_type;
56 const string_type extension = dll::shared_library::suffix().native();
57
58 // Searching a folder for files with '.so' or '.dll' extension
59 fs::recursive_directory_iterator endit;
60 for (fs::recursive_directory_iterator it(plugins_directory_); it != endit; ++it) {
61 if (!fs::is_regular_file(e: *it)) {
62 continue;
63 }
64 /*<-*/
65 if ( !b2_workarounds::is_shared_library(p: (*it).path()) ) {
66 continue;
67 }
68 /*->*/
69 // We found a file. Trying to load it
70 boost::dll::fs::error_code error;
71 dll::shared_library plugin(it->path(), error);
72 if (error) {
73 continue;
74 }
75 std::cout << "Loaded (" << plugin.native() << "):" << it->path() << '\n';
76
77 // Gets plugin using "create_plugin" or "plugin" function
78 insert_plugin(lib: boost::move(t&: plugin));
79 }
80
81 dll::shared_library plugin(dll::program_location());
82 std::cout << "Loaded self\n";
83 insert_plugin(lib: boost::move(t&: plugin));
84}
85//]
86
87//[plugcpp_plugins_collector_insert_plugin
88void plugins_collector::insert_plugin(BOOST_RV_REF(dll::shared_library) lib) {
89 std::string plugin_name;
90 if (lib.has(symbol_name: "create_plugin")) {
91 plugin_name = lib.get_alias<boost::shared_ptr<my_plugin_api>()>(alias_name: "create_plugin")()->name();
92 } else if (lib.has(symbol_name: "plugin")) {
93 plugin_name = lib.get<my_plugin_api>(symbol_name: "plugin").name();
94 } else {
95 return;
96 }
97
98 if (plugins_.find(k: plugin_name) == plugins_.cend()) {
99 plugins_[plugin_name] = boost::move(t&: lib);
100 }
101}
102//]
103
104void plugins_collector::print_plugins() const {
105 plugins_t::const_iterator const end = plugins_.cend();
106 for (plugins_t::const_iterator it = plugins_.cbegin(); it != end; ++it) {
107 std::cout << '(' << it->second.native() << "): " << it->first << '\n';
108 }
109}
110
111std::size_t plugins_collector::count() const {
112 return plugins_.size();
113}
114
115
116//[plugcpp_load_all
117int main(int argc, char* argv[]) {
118 /*<-*/
119 BOOST_ASSERT(argc >= 3);
120 boost::dll::fs::path path1(argv[1]);
121 for (int i = 2; i < argc; ++i) {
122 boost::dll::fs::path path2(argv[i]);
123 boost::dll::fs::path res;
124 for (boost::dll::fs::path::iterator it1 = path1.begin(), it2 = path2.begin();
125 it1 != path1.end() && it2 != path2.end() && *it1 == *it2;
126 ++it1, ++it2)
127 {
128 res /= *it1;
129 }
130
131 path1 = res;
132 }
133
134 std::string new_argv = path1.string();
135 std::cout << "\nPlugins path: " << new_argv << ":\n";
136 argv[1] = &new_argv[0];
137 /*->*/
138 plugins_collector plugins(argv[1]);
139
140 std::cout << "\n\nUnique plugins " << plugins.count() << ":\n";
141 plugins.print_plugins();
142 // ...
143//]
144 BOOST_ASSERT(plugins.count() >= 3);
145}
146
147

source code of boost/libs/dll/example/tutorial5/load_all.cpp