Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2018-2023 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 : #include "PlumedHandle.h" 23 : #include "core/PlumedMain.h" 24 : #include "Tools.h" 25 : #include "lepton/Exception.h" 26 : #include <cstring> 27 : #ifdef __PLUMED_HAS_DLOPEN 28 : #include <dlfcn.h> 29 : #endif 30 : 31 : // Including Plumed.h in this manner allows to create a local 32 : // implementation of the wrapper in an anonymous namespace. 33 : // This allows to avoid recoding all the Plumed.h stuff here 34 : // and at the same time avoids possible conflicts. 35 : #define __PLUMED_WRAPPER_IMPLEMENTATION 1 36 : #define __PLUMED_WRAPPER_EXTERN 0 37 : #define __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE 1 38 : #include "../wrapper/Plumed.h" 39 : 40 : namespace PLMD 41 : { 42 : 43 : 44 11 : PlumedHandle::PlumedHandle(): 45 11 : local(Tools::make_unique<PlumedMain>()) 46 : { 47 11 : } 48 : 49 1 : PlumedHandle::PlumedHandle(const char* kernel) 50 : #ifdef __PLUMED_HAS_DLOPEN 51 : : 52 1 : loaded(plumed_c2v(plumed_create_dlopen(kernel))) 53 : { 54 : if(!plumed_valid(plumed_v2c(loaded))) { 55 : // this is necessary to make sure loaded is properly destroyed 56 0 : plumed_finalize(plumed_v2c(loaded)); 57 0 : plumed_error() << "You are trying to dynamically load a kernel, but the path " << kernel <<" could not be opened"; 58 : } 59 1 : } 60 : #else 61 : { 62 : plumed_error() << "You are trying to dynamically load a kernel, but PLUMED was compiled without dlopen"; 63 : } 64 : #endif 65 : 66 12 : PlumedHandle::~PlumedHandle() { 67 12 : if(loaded) plumed_finalize(plumed_v2c(loaded)); 68 12 : } 69 : 70 1 : PlumedHandle PlumedHandle::dlopen(const char* path) { 71 1 : return PlumedHandle(path); 72 : } 73 : 74 1476 : void PlumedHandle::cmd(const std::string & key,const TypesafePtr & ptr) { 75 1476 : if(local) { 76 2508 : local->cmd(key.c_str(),ptr); 77 222 : } else if(loaded) { 78 : plumed_safeptr safe; 79 : safe.ptr=ptr.getRaw(); 80 : safe.nelem=ptr.getNelem(); 81 : safe.shape=const_cast<std::size_t*>(ptr.getShape()); 82 : safe.flags=ptr.getFlags(); 83 : safe.opt=nullptr; 84 : // try/catch needed to remap exceptions in anonymous namespace to standard plumed exceptions 85 : // this is necessary otherwise a user would not be able to catch them 86 : try { 87 222 : Plumed(loaded).cmd(key.c_str(),safe); 88 0 : } catch(PLMD::Plumed::ExceptionError& e) { 89 0 : throw ExceptionError(e.what()); 90 0 : } catch(PLMD::Plumed::ExceptionDebug& e) { 91 0 : throw ExceptionDebug(e.what()); 92 0 : } catch(PLMD::Plumed::ExceptionTypeError& e) { 93 0 : throw ExceptionError(e.what()); 94 0 : } catch(PLMD::Plumed::LeptonException& e) { 95 0 : throw lepton::Exception(e.what()); 96 0 : } catch(PLMD::Plumed::Exception& e) { 97 0 : throw Exception(e.what()); 98 0 : } 99 0 : } else plumed_error() << "should never arrive here (either one or the other should work)"; 100 1476 : } 101 : 102 0 : PlumedHandle::PlumedHandle(PlumedHandle && other) noexcept: 103 : local(std::move(other.local)), 104 0 : loaded(other.loaded) 105 : { 106 0 : other.loaded=nullptr; 107 0 : } 108 : 109 0 : PlumedHandle & PlumedHandle::operator=(PlumedHandle && other) noexcept { 110 0 : if(this!=&other) { 111 0 : if(loaded) plumed_finalize(plumed_v2c(loaded)); 112 : local=std::move(other.local); 113 0 : loaded=other.loaded; 114 0 : other.loaded=nullptr; 115 : } 116 0 : return *this; 117 : } 118 : 119 : }