23 #ifndef CASADI_PLUGIN_INTERFACE_HPP
24 #define CASADI_PLUGIN_INTERFACE_HPP
26 #include "function_internal.hpp"
27 #include "global_options.hpp"
28 #include "serializing_stream.hpp"
29 #include "casadi_os.hpp"
30 #include <casadi/config.h>
39 T check_exposed(T t) {
40 casadi_assert(t!=0,
"Static function not implemented for plugin");
44 typedef ProtoFunction* (*Deserialize)(DeserializingStream&);
52 template<
class Derived>
53 class PluginInterface {
59 typename Derived::Creator creator;
63 typename Derived::Exposed exposed;
64 const Options* options;
65 Deserialize deserialize;
67 Plugin() : creator(nullptr), name(nullptr), doc(nullptr), version(0),
68 options(nullptr), deserialize(nullptr) {}
72 typedef int (*RegFcn)(Plugin* plugin);
75 static bool has_plugin(
const std::string& pname,
bool verbose=
false);
78 static const Options& plugin_options(
const std::string& pname);
81 static Deserialize plugin_deserialize(
const std::string& pname);
84 static Plugin pluginFromRegFcn(RegFcn regfcn);
87 static Plugin load_plugin(
const std::string& pname,
bool register_plugin=
true);
90 static handle_t load_library(
const std::string& libname, std::string& resultpath,
94 static void registerPlugin(
const Plugin& plugin);
97 static void registerPlugin(RegFcn regfcn);
100 static Plugin& getPlugin(
const std::string& pname);
103 template<
class Problem>
104 static Derived* instantiate(
const std::string& fname,
105 const std::string& pname, Problem problem);
107 virtual const char* plugin_name()
const = 0;
112 void serialize_type(SerializingStream& s)
const {
113 s.pack(
"PluginInterface::plugin_name", std::string(plugin_name()));
119 static ProtoFunction* deserialize(DeserializingStream& s) {
120 std::string class_name, plugin_name;
121 s.unpack(
"PluginInterface::plugin_name", plugin_name);
122 Deserialize deserialize = plugin_deserialize(plugin_name);
123 return deserialize(s);
128 template<
class Derived>
129 bool PluginInterface<Derived>::has_plugin(
const std::string& pname,
bool verbose) {
132 if (Derived::solvers_.find(pname) != Derived::solvers_.end()) {
138 (void)load_plugin(pname,
false);
140 }
catch (CasadiException& ex) {
142 casadi_warning(ex.what());
148 template<
class Derived>
149 const Options& PluginInterface<Derived>::plugin_options(
const std::string& pname) {
150 const Options *op = getPlugin(pname).options;
151 casadi_assert(op!=
nullptr,
"Plugin \"" + pname +
"\" does not support options");
155 template<
class Derived>
156 Deserialize PluginInterface<Derived>::plugin_deserialize(
const std::string& pname) {
157 Deserialize m = getPlugin(pname).deserialize;
158 casadi_assert(m,
"Plugin \"" + pname +
"\" does not support deserialize");
162 template<
class Derived>
163 typename PluginInterface<Derived>::Plugin
164 PluginInterface<Derived>::pluginFromRegFcn(RegFcn regfcn) {
169 int flag = regfcn(&plugin);
170 casadi_assert(flag==0,
"Registration of plugin failed.");
176 template<
class Derived>
177 handle_t PluginInterface<Derived>::load_library(
const std::string& libname,
178 std::string& resultpath,
bool global) {
181 casadi_error(
"WITH_DL option needed for dynamic loading");
185 std::string lib = SHARED_LIBRARY_PREFIX + libname + SHARED_LIBRARY_SUFFIX;
188 std::vector<std::string> search_paths = get_search_paths();
189 return open_shared_library(lib, search_paths, resultpath,
190 "PluginInterface::load_plugin", global);
195 template<
class Derived>
196 typename PluginInterface<Derived>::Plugin
197 PluginInterface<Derived>::load_plugin(
const std::string& pname,
bool register_plugin) {
199 if (Derived::solvers_.find(pname) != Derived::solvers_.end()) {
200 casadi_warning(
"PluginInterface: Solver " + pname +
" is already in use. Ignored.");
206 casadi_error(
"WITH_DL option needed for dynamic loading");
212 std::string regName =
"casadi_register_" + Derived::infix_ +
"_" + pname;
214 std::string searchpath;
215 handle_t handle = load_library(
"casadi_" + Derived::infix_ +
"_" + pname, searchpath,
221 #pragma GCC diagnostic push
222 #pragma GCC diagnostic ignored "-Wcast-function-type"
224 reg =
reinterpret_cast<RegFcn
>(GetProcAddress(handle, TEXT(regName.c_str())));
226 #pragma GCC diagnostic pop
234 reg =
reinterpret_cast<RegFcn
>(dlsym(handle, regName.c_str()));
236 casadi_assert(reg!=
nullptr,
237 "PluginInterface::load_plugin: no \"" + regName +
"\" found in " + searchpath +
".");
240 Plugin plugin = pluginFromRegFcn(reg);
242 if (register_plugin) {
243 registerPlugin(plugin);
251 template<
class Derived>
252 void PluginInterface<Derived>::registerPlugin(RegFcn regfcn) {
253 registerPlugin(pluginFromRegFcn(regfcn));
256 template<
class Derived>
257 void PluginInterface<Derived>::registerPlugin(
const Plugin& plugin) {
260 typename std::map<std::string, Plugin>::iterator it=Derived::solvers_.find(plugin.name);
261 casadi_assert(it==Derived::solvers_.end(),
262 "Solver " + str(plugin.name) +
" is already in use");
265 Derived::solvers_[plugin.name] = plugin;
268 template<
class Derived>
269 typename PluginInterface<Derived>::Plugin&
270 PluginInterface<Derived>::getPlugin(
const std::string& pname) {
273 auto it=Derived::solvers_.find(pname);
276 if (it==Derived::solvers_.end()) {
278 it=Derived::solvers_.find(pname);
280 casadi_assert_dev(it!=Derived::solvers_.end());
284 template<
class Derived>
285 template<
class Problem>
286 Derived* PluginInterface<Derived>::
287 instantiate(
const std::string& fname,
288 const std::string& pname, Problem problem) {
291 if (!has_plugin(pname,
true)) {
292 casadi_error(
"Plugin '" + pname +
"' is not found.");
294 return getPlugin(pname).creator(fname, problem);