Apollo 10.0
自动驾驶开放平台
plugin_manager.h
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2023 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16#pragma once
17
18#include <map>
19#include <memory>
20#include <string>
21#include <utility>
22#include <vector>
23
24#include <cxxabi.h>
25
28#include "cyber/common/file.h"
29#include "cyber/common/log.h"
30#include "cyber/common/macros.h"
32
33namespace apollo {
34namespace cyber {
35namespace plugin_manager {
36
38 public:
40
48 bool ProcessPluginDescriptionFile(const std::string& file_path,
49 std::string* library_path);
50
57 bool LoadPlugin(const std::string& plugin_description_file_path);
58
64 static PluginManager* Instance();
65
72 template <typename Base>
73 std::shared_ptr<Base> CreateInstance(const std::string& derived_class);
74
81 bool FindPluginIndexAndLoad(const std::string& plugin_index_path);
82
89
95 template <typename Base>
96 std::string GetPluginClassHomePath(const std::string& class_name);
97
104 template <typename Base>
105 std::string GetPluginConfPath(const std::string& class_name,
106 const std::string& conf_name);
107
113 bool LoadLibrary(const std::string& library_path);
114
120 template <typename Base>
121 bool IsLibraryLoaded(const std::string& class_name);
122
128 template <typename Base>
129 bool CheckAndLoadPluginLibrary(const std::string& class_name);
130
135 template <typename Base>
136 std::vector<std::string> GetDerivedClassNameByBaseClass();
137
138 private:
140 std::map<std::string, std::shared_ptr<PluginDescription>>
141 plugin_description_map_;
142 std::map<std::string, bool> plugin_loaded_map_;
143 std::map<std::pair<std::string, std::string>, std::string>
144 plugin_class_plugin_name_map_;
145
146 static PluginManager* instance_;
147};
148
149template <typename Base>
150std::shared_ptr<Base> PluginManager::CreateInstance(
151 const std::string& derived_class) {
152 AINFO << "creating plugin instance of " << derived_class;
153 if (!CheckAndLoadPluginLibrary<Base>(derived_class)) {
154 AERROR << "plugin of class " << derived_class << " have not been loaded";
155 return nullptr;
156 }
157 return class_loader_manager_.CreateClassObj<Base>(derived_class);
158}
159
160template <typename Base>
162 const std::string& class_name) {
163 if (!CheckAndLoadPluginLibrary<Base>(class_name)) {
164 AERROR << "plugin of class " << class_name << " have not been loaded";
165 return "";
166 }
167 std::string library_path =
168 class_loader_manager_.GetClassValidLibrary<Base>(class_name);
169 if (library_path == "") {
170 AWARN << "plugin of class " << class_name << " not found";
171 return "";
172 }
173 for (auto it = plugin_description_map_.begin();
174 it != plugin_description_map_.end(); ++it) {
175 if (it->second->actual_library_path_ == library_path) {
176 // TODO(liangjinping): remove hard code of relative prefix
177 std::string relative_prefix = "share/";
178 std::string relative_plugin_home_path =
179 apollo::cyber::common::GetDirName(it->second->description_path_);
180 if (relative_plugin_home_path.rfind(relative_prefix, 0) == 0) {
181 relative_plugin_home_path =
182 relative_plugin_home_path.substr(relative_prefix.size());
183 }
184 return relative_plugin_home_path;
185 }
186 }
187 // not found
188 return "";
189}
190
191template <typename Base>
192std::string PluginManager::GetPluginConfPath(const std::string& class_name,
193 const std::string& conf_name) {
194 std::string plugin_home_path = GetPluginClassHomePath<Base>(class_name);
195 if (apollo::cyber::common::PathIsAbsolute(plugin_home_path)) {
196 // can not detect the plugin relative path
197 AWARN << "plugin of class " << class_name << " load from absolute path, "
198 << "conf path will be relative to it's description file";
199 }
200
201 std::string relative_conf_path = plugin_home_path + "/" + conf_name;
202 std::string actual_conf_path;
204 relative_conf_path, "APOLLO_CONF_PATH", &actual_conf_path)) {
205 return actual_conf_path;
206 }
207 return plugin_home_path + "/" + conf_name;
208}
209
210template <typename Base>
211bool PluginManager::IsLibraryLoaded(const std::string& class_name) {
212 int status = 0;
213 std::string base_class_name =
214 abi::__cxa_demangle(typeid(Base).name(), 0, 0, &status);
215 if (plugin_class_plugin_name_map_.find({class_name, base_class_name}) ==
216 plugin_class_plugin_name_map_.end()) {
217 // not found
218 return false;
219 }
220 std::string plugin_name =
221 plugin_class_plugin_name_map_[{class_name, base_class_name}];
222 if (plugin_loaded_map_.find(plugin_name) == plugin_loaded_map_.end()) {
223 // not found
224 return false;
225 }
226
227 return plugin_loaded_map_[plugin_name];
228}
229
230template <typename Base>
231bool PluginManager::CheckAndLoadPluginLibrary(const std::string& class_name) {
232 if (IsLibraryLoaded<Base>(class_name)) {
233 return true;
234 }
235 int status = 0;
236 std::string base_class_name =
237 abi::__cxa_demangle(typeid(Base).name(), 0, 0, &status);
238 if (plugin_class_plugin_name_map_.find({class_name, base_class_name}) ==
239 plugin_class_plugin_name_map_.end()) {
240 // not found
241 AWARN << "plugin of class " << class_name << " not found, "
242 << "please check if it's registered";
243 return false;
244 }
245 std::string plugin_name =
246 plugin_class_plugin_name_map_[{class_name, base_class_name}];
247 if (plugin_description_map_.find(plugin_name) ==
248 plugin_description_map_.end()) {
249 // not found
250 AWARN << "plugin description of class " << class_name << " not found, "
251 << "please check if it's loaded";
252 return false;
253 }
254 auto plugin_description = plugin_description_map_[plugin_name];
255 return LoadLibrary(plugin_description->actual_library_path_);
256}
257
258template <typename Base>
260 int status = 0;
261 std::string base_class_name =
262 abi::__cxa_demangle(typeid(Base).name(), 0, 0, &status);
263 std::vector<std::string> derived_class_name;
264 for (const auto& iter : plugin_class_plugin_name_map_) {
265 if (iter.first.second == base_class_name) {
266 derived_class_name.push_back(iter.first.first);
267 }
268 }
269 return derived_class_name;
270}
271
272#define CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(name, base) \
273 CLASS_LOADER_REGISTER_CLASS(name, base)
274
275} // namespace plugin_manager
276} // namespace cyber
277} // namespace apollo
Definition base.h:20
std::shared_ptr< Base > CreateClassObj(const std::string &class_name)
std::string GetClassValidLibrary(const std::string &class_name)
get pathof library that class belongs to
std::string GetPluginConfPath(const std::string &class_name, const std::string &conf_name)
get plugin configuration file location
static PluginManager * Instance()
get singleton instance of PluginManager
bool CheckAndLoadPluginLibrary(const std::string &class_name)
check if library of plugin is loaded, and load it if not
std::string GetPluginClassHomePath(const std::string &class_name)
@bried get plugin description file location that class belongs to
bool LoadInstalledPlugins()
load plugins from installed path
std::shared_ptr< Base > CreateInstance(const std::string &derived_class)
create plugin instance of derived class based on Base
bool LoadPlugin(const std::string &plugin_description_file_path)
load plugin clases from file
bool LoadLibrary(const std::string &library_path)
load library of plugin
bool IsLibraryLoaded(const std::string &class_name)
check if library of plugin is loaded
bool FindPluginIndexAndLoad(const std::string &plugin_index_path)
find plugin index file and load plugins
std::vector< std::string > GetDerivedClassNameByBaseClass()
Get all derived class name by base class name
bool ProcessPluginDescriptionFile(const std::string &file_path, std::string *library_path)
parse plugin description file and load the library TODO(liangjinping): parse description to struct
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
std::string GetDirName(const std::string &path)
get directory name of path
Definition file.cc:406
bool GetFilePathWithEnv(const std::string &path, const std::string &env_var, std::string *file_path)
get file path, judgement priority:
Definition file.cc:436
bool PathIsAbsolute(const std::string &path)
Definition file.cc:200
class register implement
Definition arena_queue.h:37