diff --git a/src/input.cpp b/src/input.cpp index 57ce64815d..07e3c417f6 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -715,10 +715,10 @@ int Input::execute_command() else if (!strcmp(command,"include")) include(); else if (!strcmp(command,"jump")) jump(); else if (!strcmp(command,"label")) label(); - else if (!strcmp(command,"load_plugin")) load_plugin(); else if (!strcmp(command,"log")) log(); else if (!strcmp(command,"next")) next_command(); else if (!strcmp(command,"partition")) partition(); + else if (!strcmp(command,"plugin")) plugin(); else if (!strcmp(command,"print")) print(); else if (!strcmp(command,"python")) python(); else if (!strcmp(command,"quit")) quit(); @@ -1031,14 +1031,6 @@ void Input::label() /* ---------------------------------------------------------------------- */ -void Input::load_plugin() -{ - if (narg != 1) error->all(FLERR,"Illegal load_plugin command"); - lammpsplugin_load(arg[0],lmp); -} - -/* ---------------------------------------------------------------------- */ - void Input::log() { if ((narg < 1) || (narg > 2)) error->all(FLERR,"Illegal log command"); @@ -1107,6 +1099,32 @@ void Input::partition() /* ---------------------------------------------------------------------- */ +void Input::plugin() +{ + if (narg < 1) error->all(FLERR,"Illegal plugin command"); + std::string cmd = arg[0]; + if (cmd == "load") { + if (narg < 2) error->all(FLERR,"Illegal plugin load command"); + for (int i=1; i < narg; ++i) + lammpsplugin_load(arg[i],lmp); + } else if (cmd == "unload") { + if (narg != 3) error->all(FLERR,"Illegal plugin unload command"); + lammpsplugin_unload(arg[1],arg[2],lmp); + } else if (cmd == "list") { + if (comm->me == 0) { + int num = lammpsplugin_get_num_plugins(); + utils::logmesg(lmp,"Currently loaded plugins\n"); + for (int i=0; i < num; ++i) { + auto entry = lammpsplugin_info(i); + utils::logmesg(lmp,fmt::format("{:4}: {} style plugin {}\n", + i+1,entry->style,entry->name)); + } + } + } else error->all(FLERR,"Illegal plugin command"); +} + +/* ---------------------------------------------------------------------- */ + void Input::print() { if (narg < 1) error->all(FLERR,"Illegal print command"); diff --git a/src/input.h b/src/input.h index 3b7b6d79c7..809a7a5f94 100644 --- a/src/input.h +++ b/src/input.h @@ -79,10 +79,10 @@ class Input : protected Pointers { void include(); void jump(); void label(); - void load_plugin(); void log(); void next_command(); void partition(); + void plugin(); void print(); void python(); void quit(); diff --git a/src/lammpsplugin.cpp b/src/lammpsplugin.cpp index 744203cd5e..3086b829c0 100644 --- a/src/lammpsplugin.cpp +++ b/src/lammpsplugin.cpp @@ -18,6 +18,7 @@ #include "lammps.h" #include "modify.h" +#include #ifdef _WIN32 #include @@ -27,6 +28,7 @@ namespace LAMMPS_NS { + static std::vector pluginlist; void lammpsplugin_load(const char *file, void *ptr) { @@ -34,7 +36,7 @@ namespace LAMMPS_NS #if defined(WIN32) utils::logmesg(lmp,"Loading of plugins not supported on Windows yet\n"); #else - void *dso = dlopen(file,RTLD_NOW); + void *dso = dlopen(file,RTLD_NOW|RTLD_GLOBAL); if (dso == nullptr) { utils::logmesg(lmp,fmt::format("Loading of plugin from file {} failed: " "{}", file, utils::getsyserror())); @@ -48,6 +50,7 @@ namespace LAMMPS_NS return; } ((lammpsplugin_initfunc)(initfunc))(ptr); +// dlclose(dso); #endif } @@ -61,6 +64,12 @@ namespace LAMMPS_NS "version {} loaded into LAMMPS " "version {}\n", plugin->info, plugin->version, lmp->version)); + lammpsplugin_entry_t entry; + entry.style = plugin->style; + entry.name = plugin->name; + entry.handle = nullptr; + pluginlist.push_back(entry); + std::string pstyle = plugin->style; if (pstyle == "pair") { (*(lmp->force->pair_map))[plugin->name] = @@ -68,6 +77,41 @@ namespace LAMMPS_NS } else { utils::logmesg(lmp,fmt::format("Loading plugin for {} styles not " "yet implemented\n", pstyle)); + pluginlist.pop_back(); + } + } + + int lammpsplugin_get_num_plugins() + { + return pluginlist.size(); + } + + const lammpsplugin_entry_t *lammpsplugin_info(int idx) + { + if ((idx < 0) || idx >= pluginlist.size()) return nullptr; + + return &pluginlist[idx]; + } + + int lammpsplugin_find(const char *style, const char *name) + { + for (int i=0; i < pluginlist.size(); ++i) { + if ((strcmp(style,pluginlist[i].style) == 0) + && (strcmp(name,pluginlist[i].name) == 0)) + return i; + } + return -1; + } + + void lammpsplugin_unload(const char *style, const char *name, void *ptr) + { + LAMMPS *lmp = (LAMMPS *)ptr; + std::string pstyle = style; + if (pstyle == "pair") { + auto found = lmp->force->pair_map->find(name); + if (found != lmp->force->pair_map->end()) { + lmp->force->pair_map->erase(found); + } } } } diff --git a/src/lammpsplugin.h b/src/lammpsplugin.h index 13076cc86f..36c442aa5e 100644 --- a/src/lammpsplugin.h +++ b/src/lammpsplugin.h @@ -14,9 +14,9 @@ #ifndef LMP_LAMMPSPLUGIN_H #define LMP_LAMMPSPLUGIN_H -#ifdef __cplusplus +// C style API and data structures required for dynamic loading + extern "C" { -#endif typedef void *(lammpsplugin_factory)(void *); typedef void (*lammpsplugin_initfunc)(void *); @@ -29,16 +29,26 @@ extern "C" { lammpsplugin_factory *creator; } lammpsplugin_t; - void lammpsplugin_init(void *); + typedef struct { + const char *style; + const char *name; + const void *handle; + } lammpsplugin_entry_t; -#ifdef __cplusplus + // prototype for initializer function required + // to load a plugin; uses C bindings + + void lammpsplugin_init(void *); } -#endif namespace LAMMPS_NS { - extern void lammpsplugin_load(const char *, void *); - extern void lammpsplugin_register(lammpsplugin_t *, void *); + extern void lammpsplugin_load(const char *, void *); + extern void lammpsplugin_register(lammpsplugin_t *, void *); + extern int lammpsplugin_get_num_plugins(); + extern const lammpsplugin_entry_t *lammpsplugin_info(int); + extern int lammpsplugin_find(const char *, const char *); + extern void lammpsplugin_unload(const char *, const char *, void *); } #endif