feat: 用Boost.DLL从指定目录用加载动态链接库!
This commit is contained in:
commit
c5204ba3a0
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# clangd的缓存目录
|
||||||
|
.cache
|
||||||
|
# 为clangd创建的compile_commands.json符号链接
|
||||||
|
compile_commands.json
|
16
README.md
Normal file
16
README.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# loader
|
||||||
|
|
||||||
|
将`/usr/lib/loader`和`/usr/local/lib/loader`里的动态链接库作为插件加载!
|
||||||
|
|
||||||
|
可以通过`LOADER_PLUGIN_DIRS`覆盖默认插件目录!
|
||||||
|
Linux下用`:`分割路径,Windows下用`;`分割路径。
|
||||||
|
|
||||||
|
为了方便测试,用
|
||||||
|
[just](https://github.com/casey/just)
|
||||||
|
封装了meson!
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ meson setup builddir
|
||||||
|
$ just install
|
||||||
|
$ /usr/local/bin/loader
|
||||||
|
```
|
11
include/interface.hpp
Normal file
11
include/interface.hpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
class BOOST_SYMBOL_VISIBLE Interface {
|
||||||
|
public:
|
||||||
|
virtual const std::string name() const = 0;
|
||||||
|
virtual ~Interface() {}
|
||||||
|
};
|
5
justfile
Normal file
5
justfile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
build:
|
||||||
|
meson compile -C builddir
|
||||||
|
|
||||||
|
install: build
|
||||||
|
meson install -C builddir
|
61
main.cpp
Normal file
61
main.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/dll/import.hpp>
|
||||||
|
|
||||||
|
#include "interface.hpp"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
namespace dll = boost::dll;
|
||||||
|
|
||||||
|
const vector<string> &get_plugin_dirs() {
|
||||||
|
static vector<string> result;
|
||||||
|
if (!result.empty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
const string delimiter = ";";
|
||||||
|
#else
|
||||||
|
const string delimiter = ":";
|
||||||
|
#endif
|
||||||
|
const char *plugin_dirs = std::getenv("LOADER_PLUGIN_DIRS");
|
||||||
|
if (plugin_dirs != nullptr && *plugin_dirs != '\0') {
|
||||||
|
boost::split(result, plugin_dirs, boost::is_any_of(delimiter));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.empty()) {
|
||||||
|
result.push_back("/usr/lib/loader");
|
||||||
|
result.push_back("/usr/local/lib/loader");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
const vector<string> &plugin_dirs = get_plugin_dirs();
|
||||||
|
for (const auto &plugin_dir : plugin_dirs) {
|
||||||
|
fs::path plugin_path(plugin_dir);
|
||||||
|
|
||||||
|
if (!fs::is_directory(plugin_path)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (fs::recursive_directory_iterator dir(plugin_path), end; dir != end; ++dir) {
|
||||||
|
boost::shared_ptr<Interface> plugin;
|
||||||
|
plugin = dll::import_symbol<Interface>(
|
||||||
|
dir->path(),
|
||||||
|
"plugin",
|
||||||
|
dll::load_mode::rtld_lazy
|
||||||
|
);
|
||||||
|
std::cout << "loading plugin: " << plugin->name() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
meson.build
Normal file
13
meson.build
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
project('loader', 'cpp',
|
||||||
|
default_options: ['cpp_std=c++20'])
|
||||||
|
|
||||||
|
inc = include_directories('include')
|
||||||
|
plugin_dep = declare_dependency(include_directories : inc)
|
||||||
|
|
||||||
|
boost_dep = dependency('boost', modules : ['filesystem'])
|
||||||
|
executable('loader', 'main.cpp',
|
||||||
|
include_directories : inc,
|
||||||
|
dependencies : boost_dep,
|
||||||
|
install : true)
|
||||||
|
|
||||||
|
subdir('plugins')
|
4
plugins/command/meson.build
Normal file
4
plugins/command/meson.build
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
command = shared_library('command', 'plugin.cpp',
|
||||||
|
dependencies : plugin_dep,
|
||||||
|
install : true,
|
||||||
|
install_dir : 'lib/loader')
|
17
plugins/command/plugin.cpp
Normal file
17
plugins/command/plugin.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "plugin.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
namespace loader {
|
||||||
|
|
||||||
|
const string Command::name() const {
|
||||||
|
return "command";
|
||||||
|
}
|
||||||
|
Command::~Command() {
|
||||||
|
std::cout << "destructing command" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
18
plugins/command/plugin.hpp
Normal file
18
plugins/command/plugin.hpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "interface.hpp"
|
||||||
|
|
||||||
|
namespace loader {
|
||||||
|
|
||||||
|
class Command : public Interface {
|
||||||
|
public:
|
||||||
|
const std::string name() const;
|
||||||
|
~Command();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" BOOST_SYMBOL_EXPORT Command plugin;
|
||||||
|
Command plugin;
|
||||||
|
|
||||||
|
}
|
1
plugins/meson.build
Normal file
1
plugins/meson.build
Normal file
@ -0,0 +1 @@
|
|||||||
|
subdir('command')
|
Loading…
x
Reference in New Issue
Block a user