Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2018-2020 The plumed team 3 : (see the PEOPLE file at the root of the distribution for a list of names) 4 : 5 : See http://www.plumed.org for more information. 6 : 7 : This file is part of plumed, version 2. 8 : 9 : plumed is free software: you can redistribute it and/or modify 10 : it under the terms of the GNU Lesser General Public License as published by 11 : the Free Software Foundation, either version 3 of the License, or 12 : (at your option) any later version. 13 : 14 : plumed is distributed in the hope that it will be useful, 15 : but WITHOUT ANY WARRANTY; without even the implied warranty of 16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 : GNU Lesser General Public License for more details. 18 : 19 : You should have received a copy of the GNU Lesser General Public License 20 : along with plumed. If not, see <http://www.gnu.org/licenses/>. 21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 22 : #ifndef __PLUMED_tools_PlumedHandle_h 23 : #define __PLUMED_tools_PlumedHandle_h 24 : #include "core/PlumedMainInitializer.h" 25 : #include <memory> 26 : 27 : namespace PLMD 28 : { 29 : 30 : class PlumedMain; 31 : 32 : /** 33 : Tiny local class to load a PLUMED kernel. 34 : 35 : Maps command to either a loaded PLUMED kernel or to the present one. 36 : It is a simplified version of the interface located at wrapper/Plumed.h. 37 : Differences are: 38 : - It does not use the `PLUMED_KERNEL` env var. Indeed, it would not make sense to use it, 39 : since this class is meant to load different kernels. 40 : - It does not implement interoperability with C/FORTRAN interfaces. 41 : - It does not implement global versions (e.g. PLMD::Plumed::gcmd). 42 : - It does not implement PLMD::Plumed::ginitialized. If it cannot be loaded, it crashes in its constructor. 43 : This will make sure that once constructed the object is usable. 44 : 45 : The mechanism for loading the kernel is anyway very similar to the one in wrapper/Plumed.c. 46 : In particular, it can load both kernels from PLUMED <=2.4 and >=2.5, and it 47 : tries to load the `libplumed.so` object if the `libplumedKernel.so` object does not load correctly. 48 : It can also be created without passing any kernel path. In that case it refers to the current one 49 : (the one to which this class belongs). 50 : 51 : The following syntax creates a handle referring to the current kernel 52 : \verbatim 53 : PlumedHandle p; 54 : // Alternatively: 55 : // auto p=PlumedHandle(); 56 : p.cmd("init"); 57 : \endverbatim 58 : 59 : The following syntax instead creates a handle referring to a loaded kernel 60 : \verbatim 61 : PlumedHandle p(PlumedHandle::dlopen("/path/to/libplumedkernel.so"); 62 : // Alternatively: 63 : // auto p=PlumedHandle::dlopen("/path/to/libplumedkernel.so"); 64 : p.cmd("init"); 65 : \endverbatim 66 : 67 : Notice that if there are problems loading the kernel an exception is thrown. 68 : Thus, once constructed the object is guaranteed to be functional. 69 : 70 : */ 71 : class PlumedHandle { 72 : /// Automatically dlclosing auxiliary class. 73 : /// Just used to make sure that handle is dlclosed correctly. 74 : class DlHandle { 75 : void *handle=nullptr; 76 : public: 77 : /// Default construct as nullptr 78 11 : DlHandle() {} 79 : /// Construct from a void* 80 0 : explicit DlHandle(void*h): handle(h) {} 81 : /// Destructor will call dlclose if necessary 82 : ~DlHandle(); 83 : /// Covertible to void* so that it can be used directly 84 : operator void*() const { 85 0 : return handle; 86 : } 87 : }; 88 : /// Pointer to PlumedMain. 89 : /// Used when using the current kernel in order to avoid unneeded indirections. 90 : std::unique_ptr<PlumedMain> local; 91 : /// Pointer to dlsym handle used to open the kernel. 92 : /// Null when using current kernel. 93 : DlHandle handle; 94 : /// Pointer to symbol table. 95 : /// Used for kernels>=2.5. We store it here since it is needed 96 : /// in constructor to initialize create_/cmd_/finalize_. 97 : /// Later on we might use the additional version information that it carries. 98 : plumed_symbol_table_type* const symbol_=nullptr; 99 : /// Pointer to create function. 100 : /// Used when kernel is dlopened. 101 : const plumed_create_pointer create_=nullptr; 102 : /// Pointer to cmd function. 103 : /// Used when kernel is dlopened. 104 : const plumed_cmd_pointer cmd_=nullptr; 105 : /// Pointer to finalize function. 106 : /// Used when kernel is dlopened. 107 : const plumed_finalize_pointer finalize_=nullptr; 108 : /// Pointer to the plumed object. 109 : /// Used when kernel is dlopened. 110 : void* const p=nullptr; 111 : /// Constructor using the path to a kernel. 112 : /// I keep it private to avoid confusion wrt the 113 : /// similar constructor of PLMD::Plumed that accepts a string (conversion from FORTRAN). 114 : explicit PlumedHandle(const char* path); 115 : public: 116 : /// Default constructor. 117 : /// Maps following commands to the current kernel. 118 : PlumedHandle(); 119 : /// Construct a PlumedHandle given the path to a kernel. 120 : /// It just uses the private constructor PlumedHandle(const char* path). 121 : static PlumedHandle dlopen(const char* path); 122 : /// Destructor. 123 : /// In case a kernel was dlopened, it dlcloses it. 124 : /// I make it virtual for future extensibility, though this is not necessary now. 125 : virtual ~PlumedHandle(); 126 : /// Move constructor. 127 : PlumedHandle(PlumedHandle &&) = default; 128 : /// Execute cmd. 129 : void cmd(const char*key,const void*ptr=nullptr); 130 : }; 131 : 132 : } 133 : #endif