From 98ad2d8e5e6c26de75279cc1623efbdae302560b Mon Sep 17 00:00:00 2001
From: Giovanni Bussi <giovanni.bussi@gmail.com>
Date: Sun, 9 Sep 2018 11:41:00 +0200
Subject: [PATCH] Many small fixes

---
 .../basic/rt-make-wrappers/COLVAR.reference   |   4 +
 regtest/basic/rt-make-wrappers/main.cpp       |  17 +
 src/wrapper/Plumed.h                          | 818 +++++++++++-------
 3 files changed, 505 insertions(+), 334 deletions(-)

diff --git a/regtest/basic/rt-make-wrappers/COLVAR.reference b/regtest/basic/rt-make-wrappers/COLVAR.reference
index c98daa188..6ff848621 100644
--- a/regtest/basic/rt-make-wrappers/COLVAR.reference
+++ b/regtest/basic/rt-make-wrappers/COLVAR.reference
@@ -94,3 +94,7 @@
  0.000000 0.000000
 #! FIELDS time d
  0.000000 0.000000
+#! FIELDS time d
+ 0.000000 0.000000
+#! FIELDS time d
+ 0.000000 0.000000
diff --git a/regtest/basic/rt-make-wrappers/main.cpp b/regtest/basic/rt-make-wrappers/main.cpp
index 762cd6591..daf1a95c6 100644
--- a/regtest/basic/rt-make-wrappers/main.cpp
+++ b/regtest/basic/rt-make-wrappers/main.cpp
@@ -164,6 +164,14 @@ int main(){
       if(p) return 0;
     }
 
+// test conversions to void
+    {
+      PLMD::Plumed p;
+      void* x=plumed_c2v(p);
+      PLMD::Plumed q(x);
+      testmecpp(q);
+    }
+
     {
 // test move semantics
       PLMD::Plumed p;
@@ -255,6 +263,15 @@ int main(){
       if(plumed_valid(p)) return 0;
       plumed_finalize(p);
     }
+// test conversion to void
+    {
+      plumed p=plumed_create();
+      void* x=plumed_c2v(p);
+      plumed q=plumed_create_reference_v(x);
+      testme(q,plumed_cmd);
+      plumed_finalize(q);
+      plumed_finalize(p);
+    }
     plumed p=plumed_create();
     testme(p,plumed_cmd);
     plumed_finalize(p);
diff --git a/src/wrapper/Plumed.h b/src/wrapper/Plumed.h
index ba09899d7..0885bc26c 100644
--- a/src/wrapper/Plumed.h
+++ b/src/wrapper/Plumed.h
@@ -46,10 +46,13 @@
 #endif
 
 /*
-  1: invalid construction throws an exception
-  0: invalid construction produces an invalid object (default)
+  1: using cmd on an invalid object throws an exception
+  0: using cmd on an invalid object aborts (default)
 
   It is set to zero by default for backward compatibility.
+  Notice that setting it to 1 the C++ interface will not be compatible with
+  PLUMED < 2.5 library since it will require plumed_valid().
+  The default value might change in the future.
 */
 
 #ifdef __PLUMED_WRAPPER_CXX_THROWS
@@ -59,19 +62,22 @@
 #endif
 
 /*
-  If __PLUMED_WRAPPER_CXX_THROWS==1, use this command to throw an exception when construction is invalid.
+  If __PLUMED_WRAPPER_CXX_THROWS==1, use this command to throw an exception when acting on invalid objects.
   By default, throws a std::runtime_error.
 */
 
 #ifdef __PLUMED_WRAPPER_CXX_THROW_CMD
 #define __PLUMED_WRAPPER_CXX_THROW_CMD_ __PLUMED_WRAPPER_CXX_THROW_CMD
 #else
-#define __PLUMED_WRAPPER_CXX_THROW_CMD_ throw ::std::runtime_error(x)
+#define __PLUMED_WRAPPER_CXX_THROW_CMD_(x) throw ::std::runtime_error(x)
 #endif
 
 /*
-  1: headers such as cstdlib are included in C++ (default)
-  0: headers such as stdlib.h are included in C++
+  1: new headers such as cstdlib are included in C++ (default)
+  0: old headers such as stdlib.h are included in C++
+
+  Should only be set to zero when including the Plumed.h file in a file using the
+  old (stdlib.h) convention.
 */
 
 #ifdef __PLUMED_WRAPPER_CXX_STD
@@ -124,11 +130,24 @@
 #define __PLUMED_WRAPPER_CXX_POLYMORPHIC_ 1
 #endif
 
+/*
+  1: write on stderr changes in reference counters
+  0: do not write changes in reference counters
+
+  Used for debugging.
+*/
+
+#ifdef __PLUMED_WRAPPER_DEBUG_REFCOUNT
+#define __PLUMED_WRAPPER_DEBUG_REFCOUNT_ __PLUMED_WRAPPER_DEBUG_REFCOUNT
+#else
+#define __PLUMED_WRAPPER_DEBUG_REFCOUNT_ 0
+#endif
+
 /*
   1: make the wrapper functions extern (default)
   0: make the wrapper functions static or inline (see also __PLUMED_WRAPPER_CXX_INLINE)
 
-  If set to zero, it disables all functions that only make sense if extern, such as
+  If set to zero, it disables all functions that only make sense as extern, such as
   Fortran wrappers, global objects, and plumed_kernel_register.
 
   It can be set to zero to include multiple copies of the wrapper implementation without worrying
@@ -227,6 +246,13 @@
 #define __PLUMED_WRAPPER_STD
 #endif
 
+#if __cplusplus > 199711L
+#define __PLUMED_WRAPPER_CXX_NOEXCEPT_ noexcept
+#else
+#define __PLUMED_WRAPPER_CXX_NOEXCEPT_
+#endif
+
+
 #ifndef __PLUMED_wrapper_Plumed_h
 #define __PLUMED_wrapper_Plumed_h
 
@@ -262,18 +288,10 @@
   is hidden inside a single object type, which is described in C by a structure
   (struct \ref plumed), in C++ by a class (PLMD::Plumed) and in FORTRAN by a
   fixed-length string (CHARACTER(LEN=32)). Obviously C++ can use both struct
-  and class interfaces, but the second should be preferred. The reference interface
+  and class interfaces, but the second should be preferred since it will automatically take
+  care of objects constructions and destructions. The reference interface
   is the C one, whereas FORTRAN and C++ interfaces are implemented as wrappers
   around it.
-
-  As of PLUMED 2.5, the interfaces contains a reference counter that allows
-  for a better control of plumed initializations and deallocations.
-  This is particularly useful for the C++ interface that now
-  behaves similarly to a primitive shared pointer and can be thus copied.
-  In other languages, to use the reference counter correctly it is sufficient to
-  remember the following rule: for any `plumed_create*` call, there should be a corresponding
-  `plumed_finalize` call.
-
   In the C++ interface, all the routines are implemented as methods of PLMD::Plumed.
   In the C and FORTRAN interfaces, all the routines are named plumed_*, to
   avoid potential name clashes. Notice that the entire plumed library
@@ -294,6 +312,14 @@
   The global object should still be initialized and finalized properly.
   This global object is obviously not usable in a multithread context.
 
+  As of PLUMED 2.5, the interfaces contains a reference counter that allows
+  for a better control of plumed initializations and deallocations.
+  This is particularly useful for the C++ interface that now
+  behaves similarly to a primitive shared pointer and can be thus copied.
+  In other languages, to use the reference counter correctly it is sufficient to
+  remember the following rule: for any `plumed_create*` call, there should be a corresponding
+  `plumed_finalize` call.
+
   The basic method to send a message to plumed is
 \verbatim
   (C) plumed_cmd
@@ -368,9 +394,6 @@
   (FORTRAN)  PLUMED_F_GVALID
 \endverbatim
 
-  If you use C++ and compile your code with -D__PLUMED_WRAPPER_CXX_THROWS=1,
-  an exception will be thrown as soon as you try to construct an invalid object instead.
-
   To convert handlers between different languages, use
 \verbatim
   (C)        plumed_c2f                 (C to FORTRAN)
@@ -381,14 +404,30 @@
   (C++)      toFortran(char*)           (C++ to FORTRAN)
 \endverbatim
 
+  As of PLUMED 2.5, when using C or C++ we allow a user to explicitly store a plumed object as
+  a void pointer (indeed: that's the only thing contained in a plumed object).
+  This might be useful in case you do not want to include the Plumed.h header in some
+  of your headers. In order to convert to/from void pointers you can use the following functions
+\verbatim
+  (C)        plumed_v2c                 (void* to C)
+  (C)        plumed_c2v                 (C to void*)
+  (C++)      Plumed(void*) constructor  (void* to C++)
+  (C++)      toVoid()                   (C++ to void*)
+\endverbatim
+  Using the functions above is much safer than using directly the pointer contained in the \ref plumed struct
+  since, when compiling with debug options, it will check if the void pointer actually points to a plumed object.
+
   As of PLUMED 2.5, we added a reference count. It is in practice possible
   to create multiple `plumed` object that refer to the same environment.
   This is done using the following functions
 \verbatim
-  (C)        plumed_create_reference(plumed)
-  (FORTRAN)  plumed_f_create_reference(char*,char*)
+  (C)        plumed_create_reference     (from a C object)
+  (C)        plumed_create_reference_f   (from a FORTRAN object)
+  (C)        plumed_create_reference_v   (from a void pointer)
+  (FORTRAN)  plumed_f_create_reference   (from a FORTRAN object)
 \endverbatim
   In C++ references are managed automatically by constructors and destructor.
+  In addition, you can manually manage them (with care!) using incref() and decref().
 
   The interface of the FORTRAN functions is very similar to that of the C functions
   and is listed below:
@@ -432,11 +471,23 @@
       INTEGER,           INTENT(OUT)   :: i
 \endverbatim
 
+  Almost all C functions have a corresponding FORTRAN function.
+  As a simple mnemonic, if you know the name of the C function you can obtain the
+  corresponding FORTRAN subroutine by adding `F_` after the `PLUMED_` prefix.
+  In addition, all `plumed` objects are replaced by `CHARACTER(LEN=32)` objects
+  holding the same information. Finally, whenever a C function returns a value,
+  the corresponding FORTRAN subroutine will have an additional `INTENT(OUT)` parameter
+  passed as the its first argument.
+
+  When you compile the FORTRAN interface, wrapper functions are added with several possible
+  name mangligs, so you should not experience problems linking the plumed library with a FORTRAN file.
+
 \section ReferencePlumedH-2-5 New in PLUMED 2.5
 
   The wrappers in PLUMED 2.5 have been completely rewritten with several improvements.
-  The interface is almost perfectly backward compatible,
-  although a few new functions are introduced (explicitly marked in the documentation).
+  The interface is almost perfectly backward compatible, although the behavior of C++ constructors
+  has been modified slightly.
+  In addition, a few new functions are introduced (explicitly marked in the documentation).
   As a consequence, if your code uses some of the new functions, you will not be able
   to link it directly with an older PLUMED library (though you will still be able to load
   an older PLUMED library at runtime). In addition, the reference counter changes slightly
@@ -451,9 +502,9 @@
   - `PLUMED_LOAD_DEBUG` can be set to report more information about the loading process.
   - `PLUMED_LOAD_NAMESPACE` can be set to `LOCAL` to load the PLUMED kernel in a separate
     namespace. The default is global namespace, which is the same behavior of PLUMED <=2.4.
-  - `PLUMED_LOAD_DEEPBIND` can be set to load the PLUMED kernel in deepbind mode, thus preferring
-    the symbols defined in the library to other symbols with the same name. Only works
-    on systems supporting `RTLD_DEEPBIND` and is mostly for debugging purposes.
+  - `PLUMED_LOAD_NODEEPBIND` can be set to load the PLUMED kernel in not-deepbind mode. Deepbind
+    mode implies that the symbols defined in the library are preferred to other symbols with the same name.
+    Only works on systems supporting `RTLD_DEEPBIND` and is mostly for debugging purposes.
 
   Another difference is that the implementation of the wrappers is now completely contained in the `Plumed.h`
   file. You can see that the `Plumed.c` is much simpler now and just includes `Plumed.h`. With a similar
@@ -467,12 +518,10 @@
     should be availabe at link time. This is how `PlumedStatic.o` is produced.
   - `-D__PLUMED_WRAPPER_IMPLEMENTATION=1 -D__PLUMED_HAS_DLOPEN -D__PLUMED_WRAPPER_EXTERN=0` allows to obtain a light
     implementation of the PLUMED interface in the current translation unit. This interface is not exported, so it
-    might be repeated in multiple files. As a limitation, it does not contain the PLUMED global instance and
+    might be repeated in all the files where you need it. As a limitation, it does not contain the PLUMED global instance and
     does not implement the FORTRAN wrappers.
 
-  In addition, the plumed object now implements a reference counter. The number of references can be increased
-  by using the function \ref plumed_create_reference() (or by \ref plumed_f_create_reference()), and is decreased by \ref plumed_finalize().
-  Consider the following example
+  In addition, the plumed object now implements a reference counter.  Consider the following example
 \verbatim
   plumed p=plumed_create();
   plumed_cmd(p,"init",NULL);
@@ -484,20 +533,39 @@
 // now plumed has been really finalized
 \endverbatim
 
-  In other words, every \ref plumed_create, \ref plumed_create_dlopen, and \ref plumed_create_reference call must be matched by a \ref plumed_finalize.
+  In other words, every \ref plumed_create, \ref plumed_create_dlopen, \ref plumed_create_reference,
+  \ref plumed_create_reference_f, and \ref plumed_create_reference_v call must be matched by a \ref plumed_finalize.
+  Notice that in C++ whenever an object goes out of scope the reference counter
+  will be decreased. In addition, consider that conversion from C/FORTRAN/void* to C++ implies calling a C++ constructor, that
+  is increases the number of references by one. Converting from C++ to C/FORTRAN/void* instead does not call any constructor,
+  that is the number of references is unchanged.
+
+  The change in the behavior of C++ constructors means that the following code will behave in a backward incompatible manner:
+\verbatim
+  plumed p=plumed_create();
+  plumed_cmd(p,"init",NULL);
+  Plumed q(p);
+  plumed_finalize(p);
+// at this stage, object q still exists with PLUMED 2.5
+// on the other hand, with PLUMED 2.4 object q refers to an
+// already finalized object
+  q.cmd("whatever",NULL);
+\endverbatim
 
   Another difference is that the value of the variable `PLUMED_KERNEL` is read every time a new
   plumed object is instantiated. So, you might even use it to load different plumed versions
   simultaneously, although the preferred way to do this is using the function \ref plumed_create_dlopen.
+  Notice that if you want to load multiple versions simultaneously you should load them in a local namespace.
+  \ref plumed_create_dlopen does it automatically, whereas loading through env var `PLUMED_KERNEL` only does it if
+  you also set env var `PLUMED_NAMESPACE=LOCAL`.
 
   Finally, a few functions have been added, namely:
   - Functions to find if a plumed object is valid
-    (\ref plumed_valid(), \ref plumed_gvalid(), \ref plumed_f_valid(), \ref plumed_f_gvalid(), \ref PLMD::Plumed::valid(),
-     and \ref PLMD::Plumed::gvalid()).
+    (\ref plumed_valid(), \ref plumed_gvalid(), \ref PLMD::Plumed::valid(), and \ref PLMD::Plumed::gvalid()).
   - Functions to create a plumed object based on the path of a specific kernel
-    (\ref plumed_create_dlopen(), \ref plumed_f_create_dlopen(), and \ref PLMD::Plumed::dlopen()).
+    (\ref plumed_create_dlopen() and \ref PLMD::Plumed::dlopen()).
   - Functions to create a plumed object referencing to another one, implementing a reference counter
-    (\ref plumed_create_reference() and \ref plumed_f_create_reference() .
+    (\ref plumed_create_reference(), \ref plumed_create_reference_v(), \ref plumed_create_reference_f().
 
   These functions were not available in PLUMED <=2.4. As a consequence, if you use one of those functions
   you will loose binary compatibility with libplumed.so (or libplumed.dylib on OSX).
@@ -528,6 +596,9 @@ typedef struct {
     \brief Void pointer holding the real PlumedMain structure
 
     To maintain binary compatibility, we should not add members to this structure.
+    As of PLUMED 2.5, in order to add new components we do not store the pointer
+    to \ref PlumedMain here but rather a pointer to an intermediate private structure
+    that contains all the details.
   */
   void*p;
 } plumed;
@@ -545,7 +616,15 @@ typedef struct {
     plumed object you might use \ref plumed_valid() on the resulting object.
     Alternatively, if you use \ref plumed_cmd() on an invalid plumed object the code will abort.
     Also notice that to avoid memory leaks you should call \ref plumed_finalize()
-    to finalize a plumed object even if it is invalid.
+    to finalize a plumed object even if it is invalid:
+\verbatim
+  plumed p=plumed_create();
+  if(!plumed_valid(p)) {
+// this will happen if the PLUMED_KERNEL variable is not set correctly
+    plumed_finalize(p);
+    return whatever;
+  }
+\endverbatim
 
     \return The constructed plumed object
 */
@@ -563,6 +642,14 @@ plumed plumed_create(void);
 
     Also notice that to avoid memory leaks you should call \ref plumed_finalize()
     to finalize a plumed object even if it is invalid.
+\verbatim
+  plumed p=plumed_create(path);
+  if(!plumed_valid(p)) {
+// this will happen if the path argument is not set correctly
+    plumed_finalize(p);
+    return whatever;
+  }
+\endverbatim
 
     \return The constructed plumed object
 */
@@ -570,7 +657,7 @@ __PLUMED_WRAPPER_VISIBILITY_
 plumed plumed_create_dlopen(const char*path);
 
 /** \relates plumed
-    Create a new reference to an existing object, increasing its reference count.
+    Create a new reference to an existing object, increasing its reference count. Available as of PLUMED 2.5
 
     Use it to increase by one the reference count of a plumed object.
     The resulting pointer might be identical to the one passed as an
@@ -588,20 +675,49 @@ plumed plumed_create_dlopen(const char*path);
 // now the underlying object is destroyed.
 \endverbatim
 
+    If the `p` object is invalid, also the returned object will be invalid.
+
     \param p The plumed object that will be referenced to.
+    \return The constructed plumed object
 */
 
 __PLUMED_WRAPPER_VISIBILITY_
 plumed plumed_create_reference(plumed p);
 
 /** \relates plumed
-    \brief Constructor as invalid.
+    \brief Create a new reference to an existing object passed as a void pointer, increasing its reference count. Available as of PLUMED 2.5
+
+  \return The constructed plumed object
+*/
+__PLUMED_WRAPPER_VISIBILITY_
+plumed plumed_create_reference_v(void*v);
+
+/** \relates plumed
+    \brief Create a new reference to an existing object passed as a fortran string, increasing its reference count. Available as of PLUMED 2.5
+
+  \return The constructed plumed object
+*/
+__PLUMED_WRAPPER_VISIBILITY_
+plumed plumed_create_reference_f(const char*f);
+
+/** \relates plumed
+    \brief Constructor as invalid. Available as of PLUMED 2.5
 
    Can be used to create an object in the same state as if it was returned by
    plumed_create_dlopen with an incorrect path (or plumed_create using runtime binding
    and an incorrect PLUMED_KERNEL).
 
-   Mostly for debug.
+   Can be used to initialize a plumed object to a well-defined state without explicitly
+   creating it. The resulting object can be checked later with \ref plumed_valid.
+   Consider the following example
+\verbatim
+    plumed p;
+    p=plumed_create_invalid();
+// at this point p is initialized to a well-defined (invalid) state.
+    setenv("PLUMED_KERNEL","/path/to/kernel/libplumedKernel.so",1);
+    plumed_finalize(p);
+    p=plumed_create();
+\endverbatim
 
     \return The constructed plumed object
 */
@@ -611,7 +727,7 @@ plumed plumed_create_invalid();
 /** \relates plumed
     \brief Tells p to execute a command.
 
-    If the object is not valid, this command will abort.
+    If the object is not valid (see \ref plumed_valid), this command will abort.
 
     \param p The plumed object on which command is acting
     \param key The name of the command to be executed
@@ -643,7 +759,7 @@ void plumed_finalize(plumed p);
 /** \relates plumed
     \brief Check if plumed is installed (for runtime binding).
 
-    Notice that this is equivalent to creating a dummy object and check if it is valid.
+    Notice that this is equivalent to creating a dummy object and checking if it is valid.
 
 \verbatim
   // this:
@@ -694,7 +810,7 @@ int plumed_use_count(plumed p);
   some_routine(p);
 \endverbatim
 */
-__PLUMED_WRAPPER_VISIBILITY_
+extern
 plumed plumed_global(void);
 
 /** \relates plumed
@@ -702,7 +818,7 @@ plumed plumed_global(void);
 
     \return 1 if plumed has been initialized, 0 otherwise
 */
-__PLUMED_WRAPPER_VISIBILITY_
+extern
 int plumed_ginitialized(void);
 
 /** \relates plumed
@@ -710,7 +826,7 @@ int plumed_ginitialized(void);
 
     \note Equivalent to plumed_create(), but initialize the static global plumed object
 */
-__PLUMED_WRAPPER_VISIBILITY_
+extern
 void plumed_gcreate(void);
 
 /** \relates plumed
@@ -722,7 +838,7 @@ void plumed_gcreate(void);
 
     `plumed_gcmd(a,b);` is equivalent to `plumed_cmd(plumed_global(),a,b);`.
 */
-__PLUMED_WRAPPER_VISIBILITY_
+extern
 void plumed_gcmd(const char* key,const void* val);
 
 /** \relates plumed
@@ -732,17 +848,17 @@ void plumed_gcmd(const char* key,const void* val);
     equivalent. In particular, plumed_gfinalize() also makes sure that the global object
     is reset to its initial status. After calling it, \ref plumed_ginitialized() will thus return 0.
 */
-__PLUMED_WRAPPER_VISIBILITY_
+extern
 void plumed_gfinalize(void);
 
 /** \relates plumed
     \brief Check if global plumed object is valid. Available as of PLUMED 2.5
 
-    It might return false if plumed is not available at runtime.
+    It might return zero if plumed is not available at runtime.
 
     \return 1 if plumed is valid, 0 otherwise.
 */
-__PLUMED_WRAPPER_VISIBILITY_
+extern
 int plumed_gvalid();
 
 #endif
@@ -800,6 +916,30 @@ void c_routine(char handler[32]){
 __PLUMED_WRAPPER_VISIBILITY_
 plumed plumed_f2c(const char* c);
 
+/** \related plumed
+    \brief Converts a plumed object to a void pointer
+
+    It returns a void pointer that can be converted back to a plumed object using \ref plumed_v2c.
+    When compiling without NDEBUG, it checks if the plumed object was properly created.
+    Notice that an invalid object (see \ref plumed_valid) can be converted to void* and back.
+
+    Can be used to store a reference to a plumed object without including the Plumed.h header.
+*/
+__PLUMED_WRAPPER_VISIBILITY_
+void* plumed_c2v(plumed p);
+
+
+/** \related plumed
+    \brief Converts a void pointer to a plumed object.
+
+    It returns a plumed object from a void pointer obtained with \ref plumed_c2v.
+    When compiling without NDEBUG, it checks if the plumed object was properly created.
+
+    Can be used to store a reference to a plumed object without including the Plumed.h header.
+*/
+__PLUMED_WRAPPER_VISIBILITY_
+plumed plumed_v2c(void*);
+
 #ifdef __cplusplus
 }
 #endif
@@ -812,9 +952,9 @@ plumed plumed_f2c(const char* c);
 #else
 #include <stdlib.h>
 #endif
-
 #if __PLUMED_WRAPPER_CXX_THROWS_
 #include <exception>
+#include <stdexcept>
 #endif
 
 #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_
@@ -829,6 +969,8 @@ namespace PLMD {
 
   This class provides a C++ interface to PLUMED.
   It only containts a \ref plumed object, but wraps it with a number of useful methods.
+  All methods are inlined so as to avoid the compilation of an extra c++ file.
+
 */
 
 class Plumed {
@@ -842,21 +984,26 @@ class Plumed {
   class invalid_t {
   };
 public:
+  /**
+    Used to construct an invalid Plumed object.
+  */
   static const invalid_t invalid;
   /**
      Check if plumed is installed (for runtime binding)
      \return true if plumed is installed, false otherwise
      \note Equivalent to plumed_installed() but returns a bool
   */
-  static bool installed();
+  static bool installed() __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    return plumed_installed();
+  }
   /**
      Check if Plumed object is valid. Available as of PLUMED 2.5
-     Notice that if this header is compiled with -D__PLUMED_WRAPPER_CXX_THROWS=1
-     this is guaranteed to be always true.
      \return true if plumed is valid, false otherwise
      \note Equivalent to plumed_valid() but returns a bool
   */
-  bool valid() const;
+  bool valid() const __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    return plumed_valid(main);
+  }
   /**
      Same as \ref valid()
 
@@ -867,12 +1014,17 @@ public:
   p.cmd("init");
   \endverbatim
   */
-  operator bool()const;
+  operator bool() const __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    return plumed_valid(main);
+  }
   /**
      Returns the number of references to this object.
-    note Equivalent to plumed_use_count()
+    \note Equivalent to plumed_use_count()
   */
-  int use_count() const;
+  int use_count() const __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    return plumed_use_count(main);
+  }
+
 #if __PLUMED_WRAPPER_GLOBAL_
   /**
      Check if global-plumed has been initialized
@@ -880,18 +1032,24 @@ public:
              called), false otherwise.
      \note Equivalent to plumed_ginitialized() but returns a bool
   */
-  static bool ginitialized();
+  static bool ginitialized() __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    return plumed_ginitialized();
+  }
   /**
      Check if global-plumed is valid
      \return true if global plumed object (see global()) is valid.
      \note Equivalent to plumed_gvalid() but returns a bool
   */
-  static bool gvalid();
+  static bool gvalid() __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    return plumed_gvalid();
+  }
   /**
      Initialize global-plumed.
      \note Equivalent to plumed_gcreate()
   */
-  static void gcreate();
+  static void gcreate() __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    plumed_gcreate();
+  }
   /**
      Send a command to global-plumed
       \param key The name of the command to be executed
@@ -899,11 +1057,18 @@ public:
                  but for some choice of key it can change the content
      \note Equivalent to plumed_gcmd()
   */
-  static void gcmd(const char* key,const void* val=NULL);
+  static void gcmd(const char* key,const void* val=NULL) {
+#if __PLUMED_WRAPPER_CXX_THROWS
+    if(!plumed_gvalid()) __PLUMED_WRAPPER_CXX_THROW_CMD_("accessing an invalid global object, check your PLUMED_KERNEL variable.");
+#endif
+    plumed_gcmd(key,val);
+  }
   /**
      Finalize global-plumed
   */
-  static void gfinalize();
+  static void gfinalize() __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    plumed_gfinalize();
+  }
   /**
      Returns the Plumed global object
 
@@ -913,25 +1078,26 @@ public:
 
      \return The Plumed global object
   */
-  static Plumed global();
+  static Plumed global() __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    return plumed_global();
+  }
 #endif
   /**
      Constructor.
 
     Notice that when using runtime binding the constructed object might be
     invalid. One might check it using the \ref valid() method.
-    On the other hand, if code is compiled with -D__PLUMED_WRAPPER_CXX_THROWS=1,
-    the constructor will throw an exception if the object is invalid.
 
     \note Performs the same task a plumed_create()
   */
-  Plumed();
+Plumed()__PLUMED_WRAPPER_CXX_NOEXCEPT_ :
+  main(plumed_create())
+  {
+  }
+
   /**
      Clone a Plumed object from a FORTRAN char* handler.
 
-     Notice that if an handler to an invalid plumed object is passed and the code is compiled
-     with -D__PLUMED_WRAPPER_CXX_THROWS=1 an exception will be thrown.
-
      \param c The FORTRAN handler (a char[32]).
 
      The reference counter for the corresponding object will be increased
@@ -942,12 +1108,24 @@ public:
 // to have maximum portability of this file I do not use the explicit keyword here
 // I thus add a suppress command for cppcheck
 // cppcheck-suppress noExplicitConstructor
-  Plumed(const char*c);
+Plumed(const char*c)__PLUMED_WRAPPER_CXX_NOEXCEPT_ :
+  main(plumed_create_reference_f(c))
+  {
+  }
+
   /**
-     Clone a Plumed object from a C plumed structure
+    Create a reference from a void* pointer.
+  */
+// to have maximum portability of this file I do not use the explicit keyword here
+// I thus add a suppress command for cppcheck
+// cppcheck-suppress noExplicitConstructor
+Plumed(void*v)__PLUMED_WRAPPER_CXX_NOEXCEPT_ :
+  main(plumed_create_reference_v(v))
+  {
+  }
 
-     Notice that if a structure containing an invalid plumed object is passed and the code is compiled
-     with -D__PLUMED_WRAPPER_CXX_THROWS=1 an exception will be thrown.
+  /**
+     Clone a Plumed object from a C plumed structure
 
      \param p The C plumed structure.
 
@@ -958,7 +1136,11 @@ public:
 // to have maximum portability of this file I do not use the explicit keyword here
 // I thus add a suppress command for cppcheck
 // cppcheck-suppress noExplicitConstructor
-  Plumed(plumed p);
+Plumed(plumed p)__PLUMED_WRAPPER_CXX_NOEXCEPT_ :
+  main(plumed_create_reference(p))
+  {
+  }
+
   /** Invalid constructor.
 
     Can be used to initialize an invalid object. It might be useful to postpone
@@ -986,19 +1168,34 @@ public:
     p.cmd("init")
   \endverbatim
   */
-  Plumed(invalid_t);
+Plumed(invalid_t)__PLUMED_WRAPPER_CXX_NOEXCEPT_ :
+  main(plumed_create_invalid())
+  {
+  }
+
   /** Copy constructor.
 
     Takes a reference, incrementing the reference counter of the corresponding object.
   */
-  Plumed(const Plumed& p);
+Plumed(const Plumed& p)__PLUMED_WRAPPER_CXX_NOEXCEPT_ :
+  main(plumed_create_reference(p.main))
+  {
+  }
+
   /** Assignment operator.
 
     Takes a reference,incrementing the reference counter of the corresponding object.
   */
-  Plumed&operator=(const Plumed&p);
+  Plumed&operator=(const Plumed&p) __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    if(this != &p) {
+      if(main.p) plumed_finalize(main);
+      main=plumed_create_reference(p.main);
+    }
+    return *this;
+  }
+
   /*
-    PLUMED 2.4 requires a C++11 compiler.
+    PLUMED >= 2.4 requires a C++11 compiler.
     Anyway, since Plumed.h file might be redistributed with other codes
     and it should be possible to combine it with earlier PLUMED versions,
     we here explicitly check if C+11 is available before enabling move semantics.
@@ -1007,11 +1204,22 @@ public:
   /** Move constructor.
     Only if move semantics is enabled.
   */
-  Plumed(Plumed&&);
+Plumed(Plumed&&p)__PLUMED_WRAPPER_CXX_NOEXCEPT_ :
+  main(p.main)
+  {
+    p.main.p=nullptr;
+  }
   /** Move assignment.
     Only if move semantics is enabled.
   */
-  Plumed& operator=(Plumed&&);
+  Plumed& operator=(Plumed&&p)__PLUMED_WRAPPER_CXX_NOEXCEPT_  {
+    if(this != &p) {
+      if(main.p) plumed_finalize(main);
+      main=p.main;
+      p.main.p=nullptr;
+    }
+    return *this;
+  }
 #endif
   /**
     Create a PLUMED object loading a specific kernel. Available as of PLUMED 2.5.
@@ -1030,13 +1238,17 @@ public:
     p.cmd("init");
   \endverbatim
   */
-  static Plumed dlopen(const char* path);
+  static Plumed dlopen(const char* path)__PLUMED_WRAPPER_CXX_NOEXCEPT_  {
+// use decref to remove the extra reference
+    return Plumed(plumed_create_dlopen(path)).decref();
+  }
+
 
   /**
      Retrieve the C plumed structure for this object.
 
      Notice that the resulting plumed structure is a weak reference and
-     should NOT be finalized, unless a new reference is explicitly addded
+     should NOT be finalized, unless a new reference is explicitly added
   \verbatim
   Plumed p;
   plumed c=p;
@@ -1048,14 +1260,64 @@ public:
   plumed_finalize(c); // <- this is right
   \endverbatim
   */
-  operator plumed()const;
+  operator plumed()const __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    return main;
+  }
+
   /**
      Retrieve a FORTRAN handler for this object
       \param c The FORTRAN handler (a char[32]).
     Notice that the resulting plumed structure is a weak reference and
-    should NOT be finalized, unless a new reference is explicitly addded.
+    should NOT be finalized, unless a new reference is explicitly added.
+  */
+  void toFortran(char*c)const __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    plumed_c2f(main,c);
+  }
+
+  /**
+     Retrieve a void* handler for this object
+    Notice that the resulting plumed structure is a weak reference and
+    should NOT be finalized, unless a new reference is explicitly added.
   */
-  void toFortran(char*c)const;
+  void* toVoid()const __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    return plumed_c2v(main);
+  }
+
+  /**
+    Increase reference counter.
+
+    Using this method improperly might interfere with correct object construction
+    and destruction.
+    If you want to play with this, also try to compile using `-D__PLUMED_WRAPPER_DEBUG_REFCOUNT=1` and see what happens.
+
+    A possible usage is to transfer the ownership of a temporary
+    object when it is converted
+  \verbatim
+  plumed p=Plumed::dlopen(path).incref()
+  // without incref(), the just constructed object will be destroyed
+  // when the temporary object is deleted.
+  ... do stuff ...
+  plumed_finalize(p);
+  \endverbatim
+
+  */
+  Plumed& incref() __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    plumed_create_reference(main);
+    return *this;
+  }
+
+  /**
+    Decrease reference counter.
+
+    Using this method improperly might interfere with correct object construction
+    and destruction.
+    If you want to play with this, also try to compile using `-D__PLUMED_WRAPPER_DEBUG_REFCOUNT=1` and see what happens.
+  */
+  Plumed& decref() __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    plumed_finalize(main);
+    return *this;
+  }
+
   /**
      Send a command to this plumed object
       \param key The name of the command to be executed
@@ -1063,7 +1325,12 @@ public:
                  but for some choice of key it can change the content
       \note Equivalent to plumed_cmd()
   */
-  void cmd(const char*key,const void*val=NULL);
+  void cmd(const char*key,const void*val=NULL) {
+#if __PLUMED_WRAPPER_CXX_THROWS
+    if(!plumed_valid(main)) __PLUMED_WRAPPER_CXX_THROW_CMD_("accessing an invalid plumed object");
+#endif
+    plumed_cmd(main,key,val);
+  }
   /**
      Destructor
 
@@ -1073,176 +1340,14 @@ public:
      one does not use the \ref cmd method.
 
      Destructor is virtual so as to allow correct inheritance from Plumed object.
-     To avoid linking problems with g++, I specify "inline" also here (in principle
-     it should be enough to specify it down in the definition of the function, but
-     for some reason that I do not understand g++ does not inline it properly in that
-     case and complains when Plumed.h is included but Plumed.o is not linked. Anyway, the
-     way it is done here seems to work properly).
   */
 #if __PLUMED_WRAPPER_CXX_POLYMORPHIC_
-  inline virtual
-#endif
-  ~Plumed();
-};
-
-/* All methods are inlined so as to avoid the compilation of an extra c++ file */
-
-inline
-bool Plumed::installed() {
-  return plumed_installed();
-}
-
-inline
-bool Plumed::valid() const {
-  return plumed_valid(main);
-}
-
-inline
-Plumed::operator bool()const {
-  return plumed_valid(main);
-}
-
-inline
-int Plumed::use_count() const {
-  return plumed_use_count(main);
-}
-
-inline
-Plumed::Plumed():
-  main(plumed_create())
-{
-#if __PLUMED_WRAPPER_CXX_THROWS_
-  if(!plumed_valid(main)) {
-    plumed_finalize(main);
-    __PLUMED_WRAPPER_CXX_THROW_CMD_("Could not initialize a PLUMED object. Check your PLUMED_KERNEL env var.");
-  }
-#endif
-}
-
-inline
-Plumed::Plumed(const char*c):
-  main(plumed_create_reference(plumed_f2c(c)))
-{
-#if __PLUMED_WRAPPER_CXX_THROWS_
-  if(!plumed_valid(main)) __PLUMED_WRAPPER_CXX_THROW_CMD_("Could not initialize a PLUMED object. Check your PLUMED_KERNEL env var.");
-#endif
-}
-
-inline
-Plumed::Plumed(plumed p):
-  main(plumed_create_reference(p))
-{
-#if __PLUMED_WRAPPER_CXX_THROWS_
-  if(!plumed_valid(main)) __PLUMED_WRAPPER_CXX_THROW_CMD_("Could not initialize a PLUMED object. Check your PLUMED_KERNEL env var.");
+  virtual
 #endif
-}
-
-inline
-Plumed::Plumed(invalid_t):
-  main(plumed_create_invalid())
-{
-}
-
-inline
-Plumed::Plumed(const Plumed& p):
-  main(plumed_create_reference(p.main))
-{
-}
-
-inline
-Plumed& Plumed::operator=(const Plumed&p) {
-  if(this != &p) {
-    if(main.p) plumed_finalize(main);
-    main=plumed_create_reference(p.main);
+  ~Plumed() __PLUMED_WRAPPER_CXX_NOEXCEPT_ {
+    if(main.p)plumed_finalize(main);
   }
-  return *this;
-}
-
-#if __cplusplus > 199711L
-inline
-Plumed::Plumed(Plumed&& p):
-  main(p.main)
-{
-  p.main.p=nullptr;
-}
-
-inline
-Plumed& Plumed::operator=(Plumed&& p) {
-  if(this != &p) {
-    if(main.p) plumed_finalize(main);
-    main=p.main;
-    p.main.p=nullptr;
-  }
-  return *this;
-}
-#endif
-
-inline
-Plumed Plumed::dlopen(const char* path) {
-  Plumed p(plumed_create_dlopen(path));
-  plumed_finalize(p.main); // remove extra reference
-#if __PLUMED_WRAPPER_CXX_THROWS_
-// throws if the object is not valid.
-  if(!p.valid()) __PLUMED_WRAPPER_CXX_THROW_CMD_("Could not initialize a PLUMED object with the given path.");
-#endif
-  return p;
-}
-
-inline
-Plumed::operator plumed()const {
-  return main;
-}
-
-inline
-void Plumed::toFortran(char*c)const {
-  plumed_c2f(main,c);
-}
-
-inline
-void Plumed::cmd(const char*key,const void*val) {
-  plumed_cmd(main,key,val);
-}
-
-inline
-Plumed::~Plumed() {
-  if(main.p)plumed_finalize(main);
-}
-
-#if __PLUMED_WRAPPER_GLOBAL_
-inline
-bool Plumed::ginitialized() {
-  return plumed_ginitialized();
-}
-
-inline
-bool Plumed::gvalid() {
-  return plumed_gvalid();
-}
-
-inline
-void Plumed::gcreate() {
-  plumed_gcreate();
-#if __PLUMED_WRAPPER_CXX_THROWS_
-  if(!plumed_gvalid()) __PLUMED_WRAPPER_CXX_THROW_CMD_("Could not initialize the global PLUMED object. Check your PLUMED_KERNEL env var.");
-#endif
-}
-
-inline
-void Plumed::gcmd(const char* key,const void* val) {
-  plumed_gcmd(key,val);
-}
-
-inline
-void Plumed::gfinalize() {
-  plumed_gfinalize();
-}
-
-inline
-Plumed Plumed::global() {
-  return plumed_global();
-}
-
-#endif
+};
 
 }
 
@@ -1312,17 +1417,6 @@ typedef struct {
   plumed_plumedmain_function_holder functions;
 } plumed_symbol_table_type;
 
-/**
-  Historically (PLUMED<=2.4) register for plumedmain function pointers.
-  As of PLUMED>=2.5, this function does not do anything except for reporting the attempt to register
-  something. It always returns NULL. The function should be here anyway to allow an incomplete
-  libplumedKernel (<=2.4), expecting this function to be present, to be loaded correctly.
-*/
-#if __PLUMED_WRAPPER_KERNEL_REGISTER_
-/* Since it is only called from outside, it must be hardcoded to be extern */
-extern plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder*);
-#endif
-
 /* Utility to convert function pointers to pointers, just for the sake of printing them */
 #define __PLUMED_CONVERT_FPTR(ptr,fptr) { ptr=NULL; __PLUMED_WRAPPER_STD memcpy(&ptr,&fptr,(sizeof(fptr)>sizeof(ptr)?sizeof(ptr):sizeof(fptr))); }
 
@@ -1331,7 +1425,15 @@ extern plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_pl
 #define __PLUMED_MALLOC __PLUMED_WRAPPER_STD malloc
 #define __PLUMED_FREE __PLUMED_WRAPPER_STD free
 
+/**
+  Historically (PLUMED<=2.4) register for plumedmain function pointers.
+  As of PLUMED>=2.5, this function does not do anything except for reporting the attempt to register
+  something. It always returns NULL. The function should be here anyway to allow an incomplete
+  libplumedKernel (<=2.4), expecting this function to be present, to be loaded correctly.
+*/
 #if __PLUMED_WRAPPER_KERNEL_REGISTER_
+/* Since it is only called from outside, it must be hardcoded to be extern */
+extern plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder*);
 plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder* f) {
   void* tmpptr;
   if(f) {
@@ -1398,11 +1500,10 @@ static void* plumed_attempt_dlopen(const char*path,int mode) {
 
 /**
   Utility to search for a function.
-  Notice that it uses tmpptr and debug. Only to be used within plumed_search_symbols
 */
-#define __PLUMED_SEARCH_FUNCTION(func,name) \
+#define __PLUMED_SEARCH_FUNCTION(tmpptr,handle,func,name,debug) \
   if(!func) { \
-    tmpptr=dlsym(p,name); \
+    tmpptr=dlsym(handle,name); \
     if(tmpptr) { \
       *(void **)(&func)=tmpptr; \
       if(debug) __PLUMED_FPRINTF(stderr,"+++ %s found at %p +++\n",name,tmpptr); \
@@ -1417,8 +1518,8 @@ Search symbolds in a dlopened library.
 This function is declared static (internal linkage) so that it is not visible from outside.
 It is first declared then defined to make sure it is a regular C static function.
 */
-static void plumed_search_symbols(void* p, plumed_plumedmain_function_holder* f,plumed_symbol_table_type** table);
-static void plumed_search_symbols(void* p, plumed_plumedmain_function_holder* f,plumed_symbol_table_type** table) {
+static void plumed_search_symbols(void* handle, plumed_plumedmain_function_holder* f,plumed_symbol_table_type** table);
+static void plumed_search_symbols(void* handle, plumed_plumedmain_function_holder* f,plumed_symbol_table_type** table) {
   plumed_plumedmain_function_holder functions;
   plumed_symbol_table_type* table_ptr;
   void* tmpptr;
@@ -1437,7 +1538,7 @@ static void plumed_search_symbols(void* p, plumed_plumedmain_function_holder* f,
     unnecessary and might be removed at some point.
   */
   debug=__PLUMED_GETENV("PLUMED_LOAD_DEBUG");
-  table_ptr=(plumed_symbol_table_type*) dlsym(p,"plumed_symbol_table");
+  table_ptr=(plumed_symbol_table_type*) dlsym(handle,"plumed_symbol_table");
   if(table_ptr) functions=table_ptr->functions;
   if(debug) {
     if(table_ptr) {
@@ -1454,12 +1555,12 @@ static void plumed_search_symbols(void* p, plumed_plumedmain_function_holder* f,
     }
   }
   /* only searches if they were not found already */
-  __PLUMED_SEARCH_FUNCTION(functions.create,"plumedmain_create");
-  __PLUMED_SEARCH_FUNCTION(functions.create,"plumed_plumedmain_create");
-  __PLUMED_SEARCH_FUNCTION(functions.cmd,"plumedmain_cmd");
-  __PLUMED_SEARCH_FUNCTION(functions.cmd,"plumed_plumedmain_cmd");
-  __PLUMED_SEARCH_FUNCTION(functions.finalize,"plumedmain_finalize");
-  __PLUMED_SEARCH_FUNCTION(functions.finalize,"plumed_plumedmain_finalize");
+  __PLUMED_SEARCH_FUNCTION(tmpptr,handle,functions.create,"plumedmain_create",debug);
+  __PLUMED_SEARCH_FUNCTION(tmpptr,handle,functions.create,"plumed_plumedmain_create",debug);
+  __PLUMED_SEARCH_FUNCTION(tmpptr,handle,functions.cmd,"plumedmain_cmd",debug);
+  __PLUMED_SEARCH_FUNCTION(tmpptr,handle,functions.cmd,"plumed_plumedmain_cmd",debug);
+  __PLUMED_SEARCH_FUNCTION(tmpptr,handle,functions.finalize,"plumedmain_finalize",debug);
+  __PLUMED_SEARCH_FUNCTION(tmpptr,handle,functions.finalize,"plumed_plumedmain_finalize",debug);
   if(functions.create && functions.cmd && functions.finalize) {
     if(debug) __PLUMED_FPRINTF(stderr,"+++ PLUMED was loaded correctly +++\n");
     *f=functions;
@@ -1484,10 +1585,10 @@ static void plumed_search_symbols(void* p, plumed_plumedmain_function_holder* f,
   (if available).
   Notice that problems can be detected checking if the functions have a NULL ptr.
   On the other hand, the symbol table pointer might be NULL just because the plumed version is <=2.4.
-  If handle is not NULL, it is used to return a dlopen handle that should be subsequently dlclosed.
+  If handle is not NULL, it is used to return a dlopen handle that could be subsequently dlclosed.
 */
-static plumed_plumedmain_function_holder plumed_retrieve_functions(plumed_symbol_table_type** plumed_symbol_table_ptr,void** handle);
-static plumed_plumedmain_function_holder plumed_retrieve_functions(plumed_symbol_table_type** plumed_symbol_table_ptr,void** handle) {
+static void plumed_retrieve_functions(plumed_plumedmain_function_holder* functions, plumed_symbol_table_type** plumed_symbol_table_ptr,void** handle);
+static void plumed_retrieve_functions(plumed_plumedmain_function_holder* functions, plumed_symbol_table_type** plumed_symbol_table_ptr,void** handle) {
 #if defined(__PLUMED_STATIC_KERNEL)
   /* Real interface */
   /* These functions are defined in the plumedKernel library */
@@ -1504,15 +1605,16 @@ static plumed_plumedmain_function_holder plumed_retrieve_functions(plumed_symbol
   plumed_plumedmain_function_holder g= {&plumed_plumedmain_create,&plumed_plumedmain_cmd,&plumed_plumedmain_finalize};
   if(plumed_symbol_table_ptr) *plumed_symbol_table_ptr=&plumed_symbol_table;
   if(handle) *handle=NULL;
-  return g;
+  if(functions) *functions=g;
 #elif ! defined(__PLUMED_HAS_DLOPEN)
   /*
     When dlopen is not available, we hard code them to NULL
   */
+  fprintf(stderr,"+++ PLUMED has been compiled without dlopen and without a static kernel +++\n");
   plumed_plumedmain_function_holder g= {NULL,NULL,NULL};
   if(plumed_symbol_table_ptr) *plumed_symbol_table_ptr=NULL;
   if(handle) *handle=NULL;
-  return g;
+  if(functions) *functions=g;
 #else
   /*
     On the other hand, for runtime binding, we use dlsym to find the relevant functions.
@@ -1548,24 +1650,27 @@ static plumed_plumedmain_function_holder plumed_retrieve_functions(plumed_symbol
   if(path && (*path)) {
     fprintf(stderr,"+++ Loading the PLUMED kernel runtime +++\n");
     fprintf(stderr,"+++ PLUMED_KERNEL=\"%s\" +++\n",path);
+    if(debug) __PLUMED_FPRINTF(stderr,"+++ Loading with mode RTLD_NOW");
+    dlopenmode=RTLD_NOW;
     if(__PLUMED_GETENV("PLUMED_LOAD_NAMESPACE") && !__PLUMED_WRAPPER_STD strcmp(__PLUMED_GETENV("PLUMED_LOAD_NAMESPACE"),"LOCAL")) {
-      dlopenmode=RTLD_NOW|RTLD_LOCAL;
-      if(debug) __PLUMED_FPRINTF(stderr,"+++ Loading with mode RTLD_NOW|RTLD_LOCAL +++\n");
+      dlopenmode=dlopenmode|RTLD_LOCAL;
+      if(debug) __PLUMED_FPRINTF(stderr,"|RTLD_LOCAL");
     } else {
-      dlopenmode=RTLD_NOW|RTLD_GLOBAL;
-      if(debug) __PLUMED_FPRINTF(stderr,"+++ Loading with mode RTLD_NOW|RTLD_GLOBAL +++\n");
+      dlopenmode=dlopenmode|RTLD_GLOBAL;
+      if(debug) __PLUMED_FPRINTF(stderr,"|RTLD_GLOBAL");
     }
 #ifdef RTLD_DEEPBIND
-    if(__PLUMED_GETENV("PLUMED_LOAD_DEEPBIND")) {
+    if(!__PLUMED_GETENV("PLUMED_LOAD_NODEEPBIND")) {
       dlopenmode=dlopenmode|RTLD_DEEPBIND;
-      if(debug) __PLUMED_FPRINTF(stderr,"+++ Loading with mode RTLD_DEEPBIND +++\n");
+      if(debug) __PLUMED_FPRINTF(stderr,"|RTLD_DEEPBIND");
     }
 #endif
+    if(debug) __PLUMED_FPRINTF(stderr," +++\n");
     p=plumed_attempt_dlopen(path,dlopenmode);
     if(p) plumed_search_symbols(p,&g,plumed_symbol_table_ptr);
   }
   if(handle) *handle=p;
-  return g;
+  if(functions) *functions=g;
 #endif
 }
 
@@ -1576,11 +1681,22 @@ static plumed_plumedmain_function_holder plumed_retrieve_functions(plumed_symbol
   at the cost of an extra indirection.
 */
 typedef struct {
+  /* allows errors with pointers to be found when debugging */
+  char magic[6];
+  /* reference count */
   int refcount;
+  /* handler to dlopened library. NULL if there was no library opened */
   void* dlhandle;
-  int nodlclose;
+  /* non zero if, upon destruction, the library should be dlclosed */
+  /* by default, we do not dlclose libraries since this might create problems if exceptions are handled after
+     the last plumed object has been destroyed */
+  /* in addition, when creating multiple plumed objects, it is more efficient to keep the library loaded */
+  int dlclose;
+  /* function pointers */
   plumed_plumedmain_function_holder functions;
+  /* pointer to the symbol table. NULL if kernel <=2.4 */
   plumed_symbol_table_type* table;
+  /* pointer to plumed object */
   void* p;
 } plumed_implementation;
 
@@ -1592,11 +1708,15 @@ static plumed_implementation* plumed_malloc_pimpl() {
   pimpl=(plumed_implementation*) __PLUMED_MALLOC(sizeof(plumed_implementation));
   if(!pimpl) {
     __PLUMED_FPRINTF(stderr,"+++ Allocation error +++\n");
-    __PLUMED_WRAPPER_STD exit(1);
+    __PLUMED_WRAPPER_STD abort();
   }
+  __PLUMED_WRAPPER_STD memcpy(pimpl->magic,"pLuMEd",6);
   pimpl->refcount=1;
+#if __PLUMED_WRAPPER_DEBUG_REFCOUNT_
+  fprintf(stderr,"refcount: new at %p\n",(void*)pimpl);
+#endif
   pimpl->dlhandle=NULL;
-  pimpl->nodlclose=0;
+  pimpl->dlclose=0;
   pimpl->functions.create=NULL;
   pimpl->functions.cmd=NULL;
   pimpl->functions.finalize=NULL;
@@ -1605,6 +1725,16 @@ static plumed_implementation* plumed_malloc_pimpl() {
   return pimpl;
 }
 
+#ifndef NDEBUG
+static int plumed_check_pimpl(plumed_implementation*pimpl);
+
+static int plumed_check_pimpl(plumed_implementation*pimpl) {
+  if(!pimpl) return 0;
+  if(__PLUMED_WRAPPER_STD memcmp(pimpl->magic,"pLuMEd",6)) return 0;
+  return 1;
+}
+#endif
+
 /* C wrappers: */
 
 plumed plumed_create(void) {
@@ -1615,11 +1745,14 @@ plumed plumed_create(void) {
   /* allocate space for implementation object. this is free-ed in plumed_finalize(). */
   pimpl=plumed_malloc_pimpl();
   /* store pointers in pimpl */
-  pimpl->functions=plumed_retrieve_functions(&pimpl->table,&pimpl->dlhandle);
+  plumed_retrieve_functions(&pimpl->functions,&pimpl->table,&pimpl->dlhandle);
   /* note if handle should not be dlclosed */
-  /* Notice that PLUMED_LOAD_NODLCLOSE only affects the kernel linked from PLUMED_KERNEL
-     and is not used in plumed_create_dlopen() */
-  pimpl->nodlclose=__PLUMED_GETENV("PLUMED_LOAD_NODLCLOSE")!=NULL;
+  /* Notice that PLUMED_LOAD_DLCLOSE only affects the kernel linked from PLUMED_KERNEL
+     and is not used in plumed_create_dlopen().
+     It might make sense in combination with PLUMED_LOAD_NODEEPBIND to avoid clashes.
+     However, it is probably useless.
+  */
+  pimpl->dlclose=__PLUMED_GETENV("PLUMED_LOAD_DLCLOSE")!=NULL;
   /* in case of failure, return */
   /* the resulting object should be plumed_finalized, though you cannot use plumed_cmd */
   if(!pimpl->functions.create) {
@@ -1642,9 +1775,12 @@ plumed plumed_create_dlopen(const char*path) {
   plumed p;
   /* pointer to implementation */
   plumed_implementation* pimpl;
+#ifdef __PLUMED_HAS_DLOPEN
   int dlopenmode;
+#endif
   /* allocate space for implementation object. this is free-ed in plumed_finalize(). */
   pimpl=plumed_malloc_pimpl();
+  /* plumed_create_dlopen always uses RTLD_LOCAL and, when possible, RTLD_DEEPBIND to allow multiple versions */
 #ifdef __PLUMED_HAS_DLOPEN
   dlopenmode=RTLD_NOW|RTLD_LOCAL;
 #ifdef RTLD_DEEPBIND
@@ -1671,17 +1807,27 @@ plumed plumed_create_reference(plumed p) {
   plumed_implementation* pimpl;
   /* obtain pimpl */
   pimpl=(plumed_implementation*) p.p;
-  assert(pimpl);
+  assert(plumed_check_pimpl(pimpl));
   /* increase reference count */
   pimpl->refcount++;
+#if __PLUMED_WRAPPER_DEBUG_REFCOUNT_
+  fprintf(stderr,"refcount: increase at %p\n",(void*)pimpl);
+#endif
   return p;
 }
 
+plumed plumed_create_reference_v(void*v) {
+  return plumed_create_reference(plumed_v2c(v));
+}
+
+plumed plumed_create_reference_f(const char*f) {
+  return plumed_create_reference(plumed_f2c(f));
+}
+
 plumed plumed_create_invalid() {
   plumed p;
   plumed_implementation* pimpl;
   pimpl=plumed_malloc_pimpl();
-  assert(pimpl);
   p.p=pimpl;
   return p;
 }
@@ -1691,11 +1837,11 @@ void plumed_cmd(plumed p,const char*key,const void*val) {
   plumed_implementation* pimpl;
   /* obtain pimpl */
   pimpl=(plumed_implementation*) p.p;
-  assert(pimpl);
+  assert(plumed_check_pimpl(pimpl));
   if(!pimpl->p) {
     __PLUMED_FPRINTF(stderr,"+++ ERROR: you are trying to use plumed, but it is not available +++\n");
     __PLUMED_FPRINTF(stderr,"+++ Check your PLUMED_KERNEL environment variable +++\n");
-    __PLUMED_WRAPPER_STD exit(1);
+    __PLUMED_WRAPPER_STD abort();
   }
   assert(pimpl->functions.create);
   assert(pimpl->functions.cmd);
@@ -1708,9 +1854,12 @@ void plumed_finalize(plumed p) {
   plumed_implementation* pimpl;
   /* obtain pimpl */
   pimpl=(plumed_implementation*) p.p;
-  assert(pimpl);
+  assert(plumed_check_pimpl(pimpl));
   /* decrease reference count */
   pimpl->refcount--;
+#if __PLUMED_WRAPPER_DEBUG_REFCOUNT_
+  fprintf(stderr,"refcount: decrease at %p\n",(void*)pimpl);
+#endif
   if(pimpl->refcount>0) return;
   /* to allow finalizing an invalid plumed object, we only call
      finalize if the object is valid */
@@ -1723,19 +1872,23 @@ void plumed_finalize(plumed p) {
   }
 #ifdef __PLUMED_HAS_DLOPEN
   /* dlclose library */
-  if(pimpl->dlhandle && !pimpl->nodlclose) dlclose(pimpl->dlhandle);
+  if(pimpl->dlhandle && pimpl->dlclose) {
+    if(__PLUMED_GETENV("PLUMED_LOAD_DEBUG")) fprintf(stderr,"+++ Unloading library\n");
+    dlclose(pimpl->dlhandle);
+  }
+#endif
+#if __PLUMED_WRAPPER_DEBUG_REFCOUNT_
+  fprintf(stderr,"refcount: delete at %p\n",(void*)pimpl);
 #endif
   /* free pimpl space */
   __PLUMED_FREE(pimpl);
-  /* reset to null */
-  p.p=NULL;
 }
 
 int plumed_valid(plumed p) {
   plumed_implementation* pimpl;
   /* obtain pimpl */
   pimpl=(plumed_implementation*) p.p;
-  assert(pimpl);
+  assert(plumed_check_pimpl(pimpl));
   if(pimpl->p) return 1;
   else return 0;
 }
@@ -1744,7 +1897,7 @@ int plumed_use_count(plumed p) {
   plumed_implementation* pimpl;
   /* obtain pimpl */
   pimpl=(plumed_implementation*) p.p;
-  assert(pimpl);
+  assert(plumed_check_pimpl(pimpl));
   return pimpl->refcount;
 }
 
@@ -1843,6 +1996,17 @@ plumed plumed_f2c(const char*c) {
   return p;
 }
 
+void* plumed_c2v(plumed p) {
+  assert(plumed_check_pimpl((plumed_implementation*)p.p));
+  return p.p;
+}
+
+plumed plumed_v2c(void* v) {
+  assert(plumed_check_pimpl((plumed_implementation*)v));
+  plumed p;
+  p.p=v;
+  return p;
+}
 
 #if __PLUMED_WRAPPER_FORTRAN_
 
@@ -1872,40 +2036,27 @@ plumed plumed_f2c(const char*c) {
   static void lower ## _static arg1
 
 __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create,PLUMED_F_CREATE,(char*c),(c)) {
-  plumed p;
-  p=plumed_create();
-  plumed_c2f(p,c);
+  plumed_c2f(plumed_create(),c);
 }
 
 __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create_dlopen,PLUMED_F_CREATE_DLOPEN,(char*c,char*path),(c,path)) {
-  plumed p;
-  p=plumed_create_dlopen(path);
-  plumed_c2f(p,c);
+  plumed_c2f(plumed_create_dlopen(path),c);
 }
 
 __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create_reference,PLUMED_F_CREATE_REFERENCE,(char* c,char*r),(c,r)) {
-  plumed p,q;
-  p=plumed_f2c(r);
-  q=plumed_create_reference(p);
-  plumed_c2f(q,c);
+  plumed_c2f(plumed_create_reference_f(r),c);
 }
 
 __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create_invalid,PLUMED_F_CREATE_INVALID,(char* c),(c)) {
-  plumed p;
-  p=plumed_create_invalid();
-  plumed_c2f(p,c);
+  plumed_c2f(plumed_create_invalid(),c);
 }
 
 __PLUMED_IMPLEMENT_FORTRAN(plumed_f_cmd,PLUMED_F_CMD,(char*c,char*key,void*val),(c,key,val)) {
-  plumed p;
-  p=plumed_f2c(c);
-  plumed_cmd(p,key,val);
+  plumed_cmd(plumed_f2c(c),key,val);
 }
 
 __PLUMED_IMPLEMENT_FORTRAN(plumed_f_finalize,PLUMED_F_FINALIZE,(char*c),(c)) {
-  plumed p;
-  p=plumed_f2c(c);
-  plumed_finalize(p);
+  plumed_finalize(plumed_f2c(c));
 }
 
 __PLUMED_IMPLEMENT_FORTRAN(plumed_f_installed,PLUMED_F_INSTALLED,(int*i),(i)) {
@@ -1915,17 +2066,13 @@ __PLUMED_IMPLEMENT_FORTRAN(plumed_f_installed,PLUMED_F_INSTALLED,(int*i),(i)) {
 
 /* New in PLUMED 2.5 */
 __PLUMED_IMPLEMENT_FORTRAN(plumed_f_valid,PLUMED_F_VALID,(char*c,int*i),(c,i)) {
-  plumed p;
   assert(i);
-  p=plumed_f2c(c);
-  *i=plumed_valid(p);
+  *i=plumed_valid(plumed_f2c(c));
 }
 
 __PLUMED_IMPLEMENT_FORTRAN(plumed_f_use_count,PLUMED_F_USE_COUNT,(char*c,int*i),(c,i)) {
-  plumed p;
   assert(i);
-  p=plumed_f2c(c);
-  *i=plumed_use_count(p);
+  *i=plumed_use_count(plumed_f2c(c));
 }
 
 #if __PLUMED_WRAPPER_GLOBAL_
@@ -1969,15 +2116,18 @@ __PLUMED_IMPLEMENT_FORTRAN(plumed_f_gvalid,PLUMED_F_GVALID,(int*i),(i)) {
 #endif
 
 #undef __PLUMED_WRAPPER_CXX_
-#undef __PLUMED_WRAPPER_CXX_THROWS_
-#undef __PLUMED_WRAPPER_CXX_THROW_CMD_
-#undef __PLUMED_WRAPPER_CXX_STD_
-#undef __PLUMED_WRAPPER_CXX_INLINE_
 #undef __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_
+#undef __PLUMED_WRAPPER_CXX_INLINE_
+#undef __PLUMED_WRAPPER_CXX_NOEXCEPT_
 #undef __PLUMED_WRAPPER_CXX_POLYMORPHIC_
+#undef __PLUMED_WRAPPER_CXX_STD_
+#undef __PLUMED_WRAPPER_CXX_THROWS_
+#undef __PLUMED_WRAPPER_CXX_THROW_CMD_
+#undef __PLUMED_WRAPPER_DEBUG_REFCOUNT_
 #undef __PLUMED_WRAPPER_EXTERN_
-#undef __PLUMED_WRAPPER_KERNEL_REGISTER_
 #undef __PLUMED_WRAPPER_FORTRAN_
 #undef __PLUMED_WRAPPER_GLOBAL_
 #undef __PLUMED_WRAPPER_IMPLEMENTATION_
+#undef __PLUMED_WRAPPER_KERNEL_REGISTER_
+#undef __PLUMED_WRAPPER_VISIBILITY_
 
-- 
GitLab