1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 Copyright (c) 2018-2021 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 DlHandle()78 DlHandle() {} 79 /// Construct from a void* DlHandle(void * h)80 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 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 134