Skip to content

Commit 95a9f2a

Browse files
Static plugin loading using symbol module resolution (#21)
* Static plugin loading using symbol moodule resolution * Avoid exceptions in isSymbolAvailable * Removed deprecated functions; revised loadLibrary function * Add method to plugin loader to load valid libraries in the correct order; revised implementation of plugin loader functions to use library loader function * Updated function signature of getAllAvailableSymbols * Return libraries specified by absolute paths at the front of the return list * Update createSharedInstance signature to match other function * Fix macro formatting * Add unit test which uses full path for library name * Add plugin achor unit test * Update decorate to support library name as full path * Add name to clang format CI --------- Co-authored-by: Michael Ripperger <michael.ripperger@swri.org>
1 parent cb57e21 commit 95a9f2a

18 files changed

+483
-235
lines changed

.clang-tidy

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Checks: >
66
clang-analyzer-*,
77
-clang-analyzer-cplusplus*,
88
bugprone-*,
9+
-bugprone-easily-swappable-parameters,
910
cppcoreguidelines-*,
1011
-cppcoreguidelines-macro-usage,
1112
-cppcoreguidelines-pro-type-static-cast-downcast,
@@ -16,6 +17,7 @@ Checks: >
1617
-cppcoreguidelines-pro-bounds-constant-array-index,
1718
-cppcoreguidelines-avoid-magic-numbers,
1819
-cppcoreguidelines-non-private-member-variables-in-classes,
20+
-cppcoreguidelines-avoid-non-const-global-variables,
1921
misc-*,
2022
-misc-non-private-member-variables-in-classes,
2123
-misc-no-recursion,
@@ -28,6 +30,7 @@ Checks: >
2830
-readability-named-parameter,
2931
-readability-magic-numbers,
3032
-readability-isolate-declaration,
33+
-readability-identifier-length,
3134
-readability-function-cognitive-complexity
3235
WarningsAsErrors: >
3336
-*,
@@ -36,6 +39,7 @@ WarningsAsErrors: >
3639
clang-analyzer-*,
3740
-clang-analyzer-cplusplus*,
3841
bugprone-*,
42+
-bugprone-easily-swappable-parameters,
3943
cppcoreguidelines-*,
4044
-cppcoreguidelines-macro-usage,
4145
-cppcoreguidelines-pro-type-static-cast-downcast,
@@ -46,6 +50,7 @@ WarningsAsErrors: >
4650
-cppcoreguidelines-pro-bounds-constant-array-index,
4751
-cppcoreguidelines-avoid-magic-numbers,
4852
-cppcoreguidelines-non-private-member-variables-in-classes,
53+
-cppcoreguidelines-avoid-non-const-global-variables,
4954
misc-*,
5055
-misc-non-private-member-variables-in-classes,
5156
-misc-no-recursion,
@@ -58,6 +63,7 @@ WarningsAsErrors: >
5863
-readability-named-parameter,
5964
-readability-magic-numbers,
6065
-readability-isolate-declaration,
66+
-readability-identifier-length,
6167
-readability-function-cognitive-complexity
6268
HeaderFilterRegex: '.*'
6369
AnalyzeTemporaryDtors: false
@@ -69,4 +75,6 @@ CheckOptions:
6975
value: '1'
7076
- key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
7177
value: '1'
78+
ExtraArgs:
79+
- '-std=c++17'
7280
...

.github/workflows/clang_format.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ on:
1010

1111
jobs:
1212
clang_format:
13-
runs-on: ubuntu-latest
13+
name: Clang-Format
14+
runs-on: ubuntu-22.04
1415
steps:
1516
- uses: actions/checkout@v4
1617

1718
- name: Run clang format
1819
run: |
1920
sudo apt update
20-
sudo apt install -y git clang-format
21+
sudo apt install -y git clang-format-14
2122
if [ $? -ge 1 ]; then return 1; fi
2223
./.run-clang-format
2324
if [ $? -ge 1 ]; then return 1; fi

.github/workflows/ubuntu.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
path: target_ws/src
3434

3535
- name: Build and Tests
36-
uses: tesseract-robotics/colcon-action@v9
36+
uses: tesseract-robotics/colcon-action@v11
3737
with:
3838
before-script: 'apt install -y -qq clang-tidy lcov'
3939
ccache-prefix: ${{ matrix.distro }}

.run-clang-format

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#!/bin/bash
2-
find . -type f -regex '.*\.\(cpp\|hpp\|cc\|cxx\|h\|hxx\)' -exec clang-format-8 -style=file -i {} \;
2+
find . -type f -regex '.*\.\(cpp\|hpp\|cc\|cxx\|h\|hxx\)' -exec clang-format-14 -style=file -i {} \;

examples/example.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@
1717
* limitations under the License.
1818
*/
1919
#include "plugin.h"
20-
#include <boost_plugin_loader/plugin_loader.h>
20+
21+
// STD
22+
#include <string>
23+
#include <vector>
2124
#include <iostream>
2225
#include <cassert>
2326

27+
// Boost Plugin Loader
28+
#include <boost_plugin_loader/plugin_loader.h>
29+
2430
using boost_plugin_loader::PluginLoader;
2531
using boost_plugin_loader::Printer;
2632
using boost_plugin_loader::Shape;
@@ -31,24 +37,24 @@ int main(int /*argc*/, char** /*argv*/) // NOLINT
3137
loader.search_paths.insert(PLUGIN_DIR);
3238
loader.search_libraries.insert(PLUGINS);
3339

34-
std::vector<std::string> printer_plugins = loader.getAvailablePlugins<Printer>();
40+
const std::vector<std::string> printer_plugins = loader.getAvailablePlugins<Printer>();
3541
assert(printer_plugins.size() == 2);
3642

3743
for (const std::string& plugin_name : printer_plugins)
3844
{
39-
std::cout << "Loading plugin '" << plugin_name << "'" << std::endl;
40-
Printer::Ptr plugin = loader.createInstance<Printer>(plugin_name);
45+
std::cout << "Loading plugin '" << plugin_name << "'\n";
46+
const Printer::Ptr plugin = loader.createInstance<Printer>(plugin_name);
4147
assert(plugin != nullptr);
4248
plugin->operator()();
4349
}
4450

45-
std::vector<std::string> shape_plugins = loader.getAvailablePlugins<Shape>();
51+
const std::vector<std::string> shape_plugins = loader.getAvailablePlugins<Shape>();
4652
assert(shape_plugins.size() == 2);
4753

4854
for (const std::string& plugin_name : shape_plugins)
4955
{
50-
std::cout << "Loading plugin '" << plugin_name << "'" << std::endl;
51-
Printer::Ptr plugin = loader.createInstance<Printer>(plugin_name);
56+
std::cout << "Loading plugin '" << plugin_name << "'\n";
57+
const Printer::Ptr plugin = loader.createInstance<Printer>(plugin_name);
5258
assert(plugin != nullptr);
5359
plugin->operator()();
5460
}

examples/plugin.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@
1717
* limitations under the License.
1818
*/
1919
#include "plugin.h"
20-
#include <boost_plugin_loader/plugin_loader.hpp>
20+
21+
// STD
22+
#include <string>
23+
24+
// Boost Plugin Loader
25+
#include <boost_plugin_loader/plugin_loader.h>
26+
#include <boost_plugin_loader/plugin_loader.hpp> // NOLINT(misc-include-cleaner)
2127

2228
namespace boost_plugin_loader
2329
{

examples/plugin.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class Printer
3434
{
3535
public:
3636
using Ptr = std::shared_ptr<Printer>;
37+
virtual ~Printer() = default;
3738
virtual void operator()() const = 0;
3839

3940
private:
@@ -47,6 +48,7 @@ class Shape
4748
{
4849
public:
4950
using Ptr = std::shared_ptr<Shape>;
51+
virtual ~Shape() = default;
5052
virtual void operator()() const = 0;
5153

5254
private:

examples/plugin_impl.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct ConsolePrinter : public Printer
2727
public:
2828
void operator()() const override
2929
{
30-
std::cout << "IMPL: ConsolePrinter" << std::endl;
30+
std::cout << "IMPL: ConsolePrinter\n";
3131
}
3232
};
3333

@@ -36,7 +36,7 @@ struct HelloWorldPrinter : public Printer
3636
public:
3737
void operator()() const override
3838
{
39-
std::cout << "IMPL: Hello World" << std::endl;
39+
std::cout << "IMPL: Hello World\n";
4040
}
4141
};
4242

@@ -45,7 +45,7 @@ struct Square : public Shape
4545
public:
4646
void operator()() const override
4747
{
48-
std::cout << "IMPL: Square" << std::endl;
48+
std::cout << "IMPL: Square\n";
4949
}
5050
};
5151

@@ -54,7 +54,7 @@ struct Triangle : public Shape
5454
public:
5555
void operator()() const override
5656
{
57-
std::cout << "IMPL: Triangle" << std::endl;
57+
std::cout << "IMPL: Triangle\n";
5858
}
5959
};
6060

include/boost_plugin_loader/macros.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,11 @@
2626
extern "C" BOOST_SYMBOL_EXPORT DERIVED_CLASS ALIAS; \
2727
BOOST_DLL_SECTION(SECTION, read) BOOST_DLL_SELECTANY DERIVED_CLASS ALIAS;
2828

29+
#define PLUGIN_ANCHOR_DECL(ANCHOR_NAME) const void* ANCHOR_NAME(); // NOLINT
30+
31+
// clang-format off
32+
#define PLUGIN_ANCHOR_IMPL(ANCHOR_NAME) \
33+
const void* ANCHOR_NAME() { return (const void*)(&ANCHOR_NAME); } // NOLINT
34+
// clang-format on
35+
2936
#endif // BOOST_PLUGIN_LOADER_MACROS_H

include/boost_plugin_loader/plugin_loader.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
#ifndef BOOST_PLUGIN_LOADER_PLUGIN_LOADER_H
2020
#define BOOST_PLUGIN_LOADER_PLUGIN_LOADER_H
2121

22+
// STD
2223
#include <set>
23-
#include <unordered_map>
2424
#include <string>
2525
#include <memory>
2626
#include <vector>
@@ -107,8 +107,7 @@ class PluginLoader
107107
* class in order to find all implementations of that plugin interface in the libraries containing plugins.
108108
*/
109109
template <class PluginBase>
110-
typename std::enable_if<has_getSection<PluginBase>::value, std::vector<std::string>>::type
111-
getAvailablePlugins() const;
110+
typename std::enable_if_t<has_getSection<PluginBase>::value, std::vector<std::string>> getAvailablePlugins() const;
112111

113112
/**
114113
* @brief Check if plugin is available
@@ -130,6 +129,20 @@ class PluginLoader
130129
*/
131130
inline std::vector<std::string> getAvailableSections(bool include_hidden = false) const;
132131

132+
/**
133+
* @brief Utility function to add library containing symbol to the search env variable
134+
*
135+
* In some cases the name and location of a library is unknown at runtime, but a symbol can
136+
* be linked at compile time. This is true for Python auditwheel distributions. This
137+
* utility function will determine the location of the library, and add it to the library search
138+
* environment variable so it can be found.
139+
*
140+
* @param symbol_ptr Pointer to the symbol to find
141+
* @param search_libraries_env The environmental variable to modify
142+
*/
143+
static inline void addSymbolLibraryToSearchLibrariesEnv(const void* symbol_ptr,
144+
const std::string& search_libraries_env);
145+
133146
/**
134147
* @brief The number of plugins stored. The size of plugins variable
135148
* @return The number of plugins.
@@ -149,12 +162,12 @@ class PluginLoader
149162
const std::set<std::string>& search_libraries) const;
150163

151164
template <typename PluginBase>
152-
typename std::enable_if<!has_getSection<PluginBase>::value, void>::type
165+
typename std::enable_if_t<!has_getSection<PluginBase>::value, void>
153166
reportError(std::ostream& msg, const std::string& plugin_name, bool search_system_folders,
154167
const std::set<std::string>& search_paths, const std::set<std::string>& search_libraries) const;
155168

156169
template <typename PluginBase>
157-
typename std::enable_if<has_getSection<PluginBase>::value, void>::type
170+
typename std::enable_if_t<has_getSection<PluginBase>::value, void>
158171
reportError(std::ostream& msg, const std::string& plugin_name, bool search_system_folders,
159172
const std::set<std::string>& search_paths, const std::set<std::string>& search_libraries) const;
160173
};

0 commit comments

Comments
 (0)