Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-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 : #ifndef __PLUMED_wrapper_Plumed_h
23 : #define __PLUMED_wrapper_Plumed_h
24 :
25 : /*
26 : This header might be included more than once in order to provide
27 : the declarations and the definitions. The guard is thus closed before the end of the file
28 : (match this brace) {
29 : and a new guard is added for the definitions.
30 : */
31 :
32 : /**
33 : \page ReferencePlumedH Reference for interfacing MD codes with PLUMED
34 :
35 : Plumed.h and Plumed.c contain the external plumed interface, which is used to
36 : integrate it with MD engines. This interface is very general, and is expected
37 : not to change across plumed versions. Plumed.c also implements a dummy version
38 : of the interface, so as to allow a code to be fully linked even if the plumed
39 : library is not available yet. These files could be directly included in the official
40 : host MD distribution. In this manner, it will be sufficient to link the plumed
41 : library at link time (on all systems) or directly at runtime (on systems where
42 : dynamic loading is enabled) to include plumed features.
43 :
44 : Notice that in PLUMED 2.5 this interface has been rewritten in order to allow
45 : more debugging features and a better behavior in multithread environments.
46 : The interface is almost perfectly backward compatible, although it implements
47 : a few additional functions. See more details below.
48 :
49 : A further improvement has been made in PLUMED 2.8, where the interface has
50 : been modified to allow dynamic type checking. See more details below.
51 :
52 : Why is Plumed.c written in C and not C++? The reason is that the resulting Plumed.o
53 : needs to be linked with the host MD code immediately (whereas the rest of plumed
54 : could be linked a posteriori). Imagine the MD code is written in FORTRAN: when we
55 : link the Plumed.o file we would like not to need any C++ library linked. In this
56 : manner, we do not need to know which C++ compiler will be used to compile plumed.
57 : The C++ library is only linked to the "rest" of plumed, which actually uses it.
58 : Anyway, Plumed.c is written in such a manner to allow its compilation also in C++
59 : (C++ is a bit stricter than C). This will
60 : allow e.g. MD codes written in C++ to just incorporate Plumed.c (maybe renamed into
61 : Plumed.cpp), without the need of configuring a plain C compiler.
62 :
63 : Plumed interface can be used from C, C++ and FORTRAN. Everything concerning plumed
64 : is hidden inside a single object type, which is described in C by a structure
65 : (struct \ref plumed), in C++ by a class (PLMD::Plumed) and in FORTRAN by a
66 : fixed-length string (CHARACTER(LEN=32)). Obviously C++ can use both struct
67 : and class interfaces, but the second should be preferred since it will automatically take
68 : care of objects constructions and destructions. The reference interface
69 : is the C one, whereas FORTRAN and C++ interfaces are implemented as wrappers
70 : around it.
71 : In the C++ interface, all the routines are implemented as methods of PLMD::Plumed.
72 : In the C and FORTRAN interfaces, all the routines are named plumed_*, to
73 : avoid potential name clashes. Notice that the entire plumed library
74 : is implemented in C++, and it is hidden inside the PLMD namespace.
75 :
76 : Handlers to the plumed object can be converted among different representations,
77 : to allow inter-operability among languages. In C, there are tools to convert
78 : to/from FORTRAN, whereas in C++ there are tools to convert to/from FORTRAN and C.
79 :
80 : These handlers only contain a pointer to the real structure, so that
81 : when a plumed object is brought from one language to another,
82 : it brings a reference to the same environment.
83 :
84 : Moreover, to simplify life in all cases where a single Plumed object is
85 : required for the entire simulation (which covers many of the practical
86 : applications with conventional MD codes) it is possible to take advantage
87 : of a global interface, which is implicitly referring to a unique global instance.
88 : The global object should still be initialized and finalized properly.
89 : This global object is obviously not usable in a multithread context. In addition,
90 : it is difficult to use it in an exception-safe manner, so its usage in C++ is
91 : allowed but discouraged.
92 :
93 : As of PLUMED 2.5, the interface contains a reference counter that allows
94 : for a better control of plumed initializations and deallocations.
95 : This is particularly useful for the C++ interface that now
96 : behaves similarly to a primitive shared pointer and can be thus copied.
97 : In other languages, to use the reference counter correctly it is sufficient to
98 : remember the following rule: for any `plumed_create*` call, there should be a corresponding
99 : `plumed_finalize` call. More examples can be found below.
100 :
101 : Notice that up to PLUMED 2.8 the reference counter was not thread safe. This is fixed
102 : when using PLUMED>=2.9 wrappers with a PLUMED>=2.9 kernel.
103 :
104 : The basic method to send a message to plumed is
105 : \verbatim
106 : (C) plumed_cmd
107 : (C++) PLMD::Plumed::cmd
108 : (FORTRAN) PLUMED_F_CMD
109 : \endverbatim
110 :
111 : To initialize a plumed object, use:
112 : \verbatim
113 : (C) plumed_create
114 : (C++) (constructor of PLMD::Plumed)
115 : (FORTRAN) PLUMED_F_CREATE
116 : \endverbatim
117 :
118 : As of PLUMED 2.5, you can also initialize a plumed object using the following functions,
119 : that load a specific kernel. The function plumed_create_dlopen2 allows to specify options
120 : for dlopen. The C++ version accepts an optional argument to this aim.
121 : \verbatim
122 : (C) plumed_create_dlopen or plumed_create_dlopen2
123 : (C++) PLMD::Plumed::dlopen
124 : (FORTRAN) PLUMED_F_CREATE_DLOPEN
125 : \endverbatim
126 :
127 : As of PLUMED 2.8, you can also initialize a plumed object using the following function,
128 : that loads a kernel from an already loaded shared library. It accepts a handler
129 : returned by `dlopen`:
130 : \verbatim
131 : (C) plumed_create_dlsym
132 : (C++) PLMD::Plumed::dlsym
133 : (FORTRAN not allowed)
134 : \endverbatim
135 :
136 : To finalize a plumed object, use
137 : \verbatim
138 : (C) plumed_finalize
139 : (C++) (destructor of PLMD::Plumed)
140 : (FORTRAN) PLUMED_F_FINALIZE
141 : \endverbatim
142 :
143 : To access to the global-object, use
144 : \verbatim
145 : (C) plumed_gcreate, plumed_gfinalize, plumed_gcmd
146 : (C++) PLMD::Plumed::gcreate, PLMD::Plumed::gfinalize, PLMD::Plumed::gcmd
147 : (FORTRAN) PLUMED_F_GCREATE, PLUMED_F_GFINALIZE, PLUMED_F_GCMD
148 : \endverbatim
149 :
150 : To check if the global object has been initialized, use
151 : \verbatim
152 : (C) plumed_ginitialized
153 : (C++) PLMD::Plumed::ginitialized
154 : (FORTRAN) PLUMED_F_GINITIALIZED
155 : \endverbatim
156 :
157 : Notice that when using runtime binding the plumed library might be not available.
158 : In this case, plumed_create (and plumed_gcreate) will still succeed, but a subsequent
159 : call to plumed_cmd (or plumed_gcmd) would exit. In order to avoid this
160 : unpleasant situation you have two options.
161 :
162 : First, you can check if plumed library is available before actually creating an object
163 : using this function:
164 : \verbatim
165 : (C) plumed_installed
166 : (C++) PLMD::Plumed::installed
167 : (FORTRAN) PLUMED_F_INSTALLED
168 : \endverbatim
169 :
170 : Alternatively, as of PLUMED 2.5, you can interrogate the just created plumed
171 : object using the following function:
172 : \verbatim
173 : (C) plumed_valid
174 : (C++) PLMD::Plumed::valid
175 : (FORTRAN) PLUMED_F_VALID
176 : \endverbatim
177 :
178 : If you want to create on purpose an invalid Plumed object (useful in C++ to postpone
179 : the loading of the library) you can use `Plumed p(Plumed::makeInvalid());`.
180 :
181 : To know if the global object is valid instead you should use the following function:
182 : \verbatim
183 : (C) plumed_gvalid
184 : (C++) PLMD::Plumed::gvalid
185 : (FORTRAN) PLUMED_F_GVALID
186 : \endverbatim
187 :
188 : To convert handlers between different languages, use
189 : \verbatim
190 : (C) plumed_c2f (C to FORTRAN)
191 : (C) plumed_f2c (FORTRAN to C)
192 : (C++) Plumed(plumed) constructor (C to C++)
193 : (C++) operator plumed() cast (C++ to C)
194 : (C++) Plumed(char*) constructor (FORTRAN to C++)
195 : (C++) toFortran(char*) (C++ to FORTRAN)
196 : \endverbatim
197 :
198 : As of PLUMED 2.5, when using C or C++ we allow a user to explicitly store a plumed object as
199 : a void pointer (indeed: that's the only thing contained in a plumed object).
200 : This might be useful in case you do not want to include the Plumed.h header in some
201 : of your headers. In order to convert to/from void pointers you can use the following functions
202 : \verbatim
203 : (C) plumed_v2c (void* to C)
204 : (C) plumed_c2v (C to void*)
205 : (C++) Plumed(void*) constructor (void* to C++)
206 : (C++) toVoid() (C++ to void*)
207 : \endverbatim
208 : Using the functions above is much safer than accessing directly the pointer contained in the \ref plumed struct
209 : since, when compiling with debug options, it will check if the void pointer actually points to a plumed object.
210 :
211 : As of PLUMED 2.5, we added a reference count. It is in practice possible
212 : to create multiple `plumed` objects that refer to the same environment.
213 : This is done using the following functions
214 : \verbatim
215 : (C) plumed_create_reference (from a C object)
216 : (C) plumed_create_reference_f (from a FORTRAN object)
217 : (C) plumed_create_reference_v (from a void pointer)
218 : (FORTRAN) plumed_f_create_reference (from a FORTRAN object)
219 : \endverbatim
220 : In C++ references are managed automatically by constructors and destructor.
221 : In addition, you can manually manage them (with care!) using incref() and decref().
222 :
223 : The interface of the FORTRAN functions is very similar to that of the C functions
224 : and is listed below:
225 :
226 : \verbatim
227 : FORTRAN interface
228 : SUBROUTINE PLUMED_F_CREATE(p)
229 : CHARACTER(LEN=32), INTENT(OUT) :: p
230 : SUBROUTINE PLUMED_F_CREATE_DLOPEN(p,path)
231 : CHARACTER(LEN=32), INTENT(OUT) :: p
232 : CHARACTER(LEN=*), INTENT(IN) :: path
233 : SUBROUTINE PLUMED_F_CREATE_REFERENCE(p,r)
234 : CHARACTER(LEN=32), INTENT(OUT) :: p
235 : CHARACTER(LEN=32), INTENT(IN) :: r
236 : SUBROUTINE PLUMED_F_CREATE_INVALID(p)
237 : CHARACTER(LEN=32), INTENT(OUT) :: p
238 : SUBROUTINE PLUMED_F_CMD(p,key,val)
239 : CHARACTER(LEN=32), INTENT(IN) :: p
240 : CHARACTER(LEN=*), INTENT(IN) :: key
241 : UNSPECIFIED_TYPE, INTENT(INOUT) :: val(*)
242 : SUBROUTINE PLUMED_F_FINALIZE(p)
243 : CHARACTER(LEN=32), INTENT(IN) :: p
244 : SUBROUTINE PLUMED_F_INSTALLED(i)
245 : INTEGER, INTENT(OUT) :: i
246 : SUBROUTINE PLUMED_F_VALID(p,i)
247 : CHARACTER(LEN=32), INTENT(IN) :: p
248 : INTEGER, INTENT(OUT) :: i
249 : SUBROUTINE PLUMED_F_USE_COUNT(p,i)
250 : CHARACTER(LEN=32), INTENT(IN) :: p
251 : INTEGER, INTENT(OUT) :: i
252 : SUBROUTINE PLUMED_F_GLOBAL(p)
253 : CHARACTER(LEN=32), INTENT(OUT) :: p
254 : SUBROUTINE PLUMED_F_GINITIALIZED(i)
255 : INTEGER, INTENT(OUT) :: i
256 : SUBROUTINE PLUMED_F_GCREATE()
257 : SUBROUTINE PLUMED_F_GCMD(key,val)
258 : CHARACTER(LEN=*), INTENT(IN) :: key
259 : UNSPECIFIED_TYPE, INTENT(INOUT) :: val(*)
260 : SUBROUTINE PLUMED_F_GFINALIZE()
261 : SUBROUTINE PLUMED_F_GVALID(i)
262 : INTEGER, INTENT(OUT) :: i
263 : \endverbatim
264 :
265 : Almost all C functions have a corresponding FORTRAN function.
266 : As a simple mnemonic, if you know the name of the C function you can obtain the
267 : corresponding FORTRAN subroutine by adding `F_` after the `PLUMED_` prefix.
268 : In addition, all `plumed` objects are replaced by `CHARACTER(LEN=32)` objects
269 : holding the same information. These pointers basically contain a text representation
270 : of the stored pointer, that is suitable to be contained in a string.
271 : Finally, whenever a C function returns a value,
272 : the corresponding FORTRAN subroutine will have an additional `INTENT(OUT)` parameter
273 : passed as the its last argument.
274 :
275 : When you compile the FORTRAN interface, wrapper functions are added with several possible
276 : name manglings, so you should not experience problems linking the plumed library with a FORTRAN file.
277 :
278 : \section ReferencePlumedH-exceptions Error handling
279 :
280 : In case an error is detected by PLUMED, either because of some user error, some internal bug,
281 : or some mistake in using the library, an exception will be thrown. The behavior is different depending if you use
282 : PLUMED from C/FORTRAN or from C++.
283 :
284 : First of all, notice that access to PLUMED goes through three functions:
285 : - plumed_create: this, as of PLUMED 2.5, is guaranteed not to throw any exception. If there is a problem, it will
286 : just return a plumed object containing a NULL pointer
287 : - plumed_cmd: this function might throw exceptions.
288 : - plumed_finalize: this is a destructor and is guaranteed not to throw any exception.
289 :
290 : The following discussion concerns all the exceptions thrown by plumed_cmd.
291 :
292 : If you use C/FORTRAN, you will basically have no way to intercept the exception and the program will just terminate.
293 :
294 : If you use C++ and you are calling the C++ interface (e.g. \ref Plumed::cmd), as of PLUMED 2.5 we implemented a complete
295 : remapping of the exceptions thrown by PLUMED. This solves both the problems mentioned above. In particular:
296 : - Instead of throwing an exception, PLUMED will return (using a \ref plumed_nothrow_handler) the details about the occurred error.
297 : - An equivalent exception will be thrown within the inline PLUMED interface compiled with your MD code.
298 :
299 : As a consequence, you will be able to combine different compilers and avoid stack unwinding in the C layer.
300 :
301 : If you use C++ but you are calling the C interface (e.g. \ref plumed_cmd), then you might be
302 : able to catch the exceptions thrown by PLUMED. Notice that all the exceptions thrown by PLUMED inherit from std::exception,
303 : so you might want to catch it by reference. By default, as of PLUMED 2.8 \ref plumed_cmd is redefined as a macro and directly calls
304 : the \ref Plumed::cmd interface, and thus behaves in an equivalent manner. With previous versions of this header
305 : one could have encountered problems with stack unwinding performed during exception handling in the C layer.
306 :
307 : Notice that, even if you use \ref Plumed::cmd, if you are loading a kernel <=2.4 any exception generated by PLUMED will
308 : leak through the C layer. This might lead to undefined behavior. If you are lucky (with some compiler it works!) and
309 : the exception arrives to C, PLUMED will catch it and rethrow it as it would do if you were using a kernel >=2.5.
310 :
311 : The remapping of exceptions takes care of all the standard C++ exceptions plus all the exceptions raised within
312 : PLUMED. Unexpected exceptions that are derived from std::exception will be rethrown as std::exception.
313 : Notice that this implies some loss of information, since the original exception might have been of a different type.
314 : However, it also implies that the virtual table of the original exception won't be needed anymore. This allows to
315 : completely decouple the MD code from the PLUMED library.
316 :
317 : \section ReferencePlumedH-typesafe Typesafe interface
318 :
319 : Starting with PLUMED 2.8, the `cmd` function of the C++ interface, and the similar function `gcmd`, can be called
320 : with several interfaces and can perform a typechecking on the passed argument. In particular, the following
321 : forms are now possible:
322 : \verbatim
323 : cmd("string",value); // by value
324 : cmd("string",&value); // by pointer
325 : cmd("string",&value,nelem); // by pointer, specifying the number of elements of the passed array
326 : cmd("string",&value,shape); // by pointer, specifying the shape of the passed array
327 : \endverbati
328 : The `nelem` and `shape` arguments are used by PLUMED to check that the user
329 : provided enough elements. If nelem is provided, the check is done on the flatten array, whereas if shape
330 : is passed a more thorough check is performed controlling each of the dimensions of the array.
331 : In addition to this, the type of the pointer (or of the value) is checked at runtime.
332 :
333 : All these checks are only implemented if the PLUMED library is recent (>=2.8). However, it will still be
334 : possible to load at runtime an older PLUMED library (<=2.7). For this reason, it is still compulsory
335 : to pass the correct types to the `cmd` function, also when the argument is passed by value.
336 : Type conversions are only performed between pointers and only in ways compatible with
337 : what is allowed in C++ (e.g., `const void*` cannot be converted to `void*`, but `void*` can
338 : be converted to `const void*`).
339 :
340 : Type checks can be disabled by setting `export PLUMED_TYPESAFE_IGNORE=yes` at runtime.
341 :
342 : Typechecks are also enabled in the C interface (plumed_cmd). This function is replaced with a macro by default.
343 : In particular:
344 : - If the C interface is used in C++ code, it calls the C++ interface. Can be disabled with `-D__PLUMED_WRAPPER_CXX_BIND_C=0`.
345 : - If the C interface is used in C code and compiled with a C11 compiler, it uses _Generic to pass type information.
346 : Can be disabled using `-D__PLUMED_WRAPPER_C_TYPESAFE=0`.
347 :
348 : \section ReferencePlumedH-2-5 New in PLUMED 2.5
349 :
350 : The wrappers in PLUMED 2.5 have been completely rewritten with several improvements.
351 : The interface is almost perfectly backward compatible, although the behavior of C++ constructors
352 : has been modified slightly.
353 : In addition, a few new functions are introduced (explicitly marked in the documentation).
354 : As a consequence, if your code uses some of the new functions, you will not be able
355 : to link it directly with an older PLUMED library (though you will still be able to load
356 : an older PLUMED library at runtime). In addition, the reference counter changes slightly
357 : the behavior of the C++ methods used to interoperate with C and FORTRAN.
358 :
359 : An important novelty is in the way the runtime loader is implemented.
360 : In particular, the loader works also if the symbols of the main executable are not exported.
361 : The proper functions from the kernel are indeed searched explicitly now using `dlsym`.
362 :
363 : Some additional features can be enabled using suitable environment variables. In particular:
364 : - `PLUMED_LOAD_DEBUG` can be set to report more information about the loading process.
365 : - `PLUMED_LOAD_NAMESPACE` can be set to choose in which namespace PLUMED is loaded when using runtime
366 : loading. As of version 2.10, PLUMED is loaded with RTLD_LOCAL by default. The behavior can be reverted
367 : by exporting `PLUMED_LOAD_NAMESPACE=GLOBAL`. The default setting facilitates loading multiple
368 : versions of PLUMED simultaneously.
369 : - `PLUMED_LOAD_NODEEPBIND` can be set to load the PLUMED kernel in not-deepbind mode. Deepbind
370 : mode implies that the symbols defined in the library are preferred to other symbols with the same name.
371 : Only works on systems supporting `RTLD_DEEPBIND` and is mostly for debugging purposes.
372 :
373 : Another difference is that the implementation of the wrappers is now completely contained in the `Plumed.h`
374 : file. You can see that the `Plumed.c` is much simpler now and just includes `Plumed.h`. With a similar
375 : procedure you could compile the wrappers directly into your code making it unnecessary to link
376 : the libplumedWrapper.a library. The corresponding macros are still subject to change and are not documented here.
377 :
378 : As written above, the plumed object now implements a reference counter. Consider the following example
379 : \verbatim
380 : plumed p=plumed_create();
381 : plumed_cmd(p,"init",NULL);
382 : plumed q=plumed_create_reference(p);
383 : plumed_finalize(p);
384 : // at this stage, object q still exists
385 : plumed_cmd(q,"whatever",NULL);
386 : plumed_finalize(q);
387 : // now plumed has been really finalized
388 : \endverbatim
389 :
390 : In other words, every \ref plumed_create, \ref plumed_create_dlopen, \ref plumed_create_reference,
391 : \ref plumed_create_reference_f, and \ref plumed_create_reference_v call must be matched by a \ref plumed_finalize.
392 : Notice that in C++ whenever an object goes out of scope the reference counter
393 : will be decreased. In addition, consider that conversion from C/FORTRAN/void* to C++ implies calling a C++ constructor, that
394 : is increases the number of references by one. Converting from C++ to C/FORTRAN/void* instead does not call any constructor,
395 : that is the number of references is unchanged.
396 :
397 : The change in the behavior of C++ constructors means that the following code will behave in a backward incompatible manner:
398 : \verbatim
399 : plumed p=plumed_create();
400 : plumed_cmd(p,"init",NULL);
401 : Plumed q(p);
402 : plumed_finalize(p);
403 : // at this stage, object q still exists with PLUMED 2.5
404 : // on the other hand, with PLUMED 2.4 object q refers to an
405 : // already finalized object
406 : q.cmd("whatever",NULL);
407 : \endverbatim
408 :
409 : Another difference is that the value of the variable `PLUMED_KERNEL` is read every time a new
410 : plumed object is instantiated. So, you might even use it to load different plumed versions
411 : simultaneously, although the preferred way to do this is using the function \ref plumed_create_dlopen.
412 : Notice that if you want to load multiple versions simultaneously you should load them in a local namespace.
413 : \ref plumed_create_dlopen does it automatically, whereas loading through env var `PLUMED_KERNEL` only does it if
414 : you also set env var `PLUMED_NAMESPACE=LOCAL`.
415 :
416 : Finally, a few functions have been added, namely:
417 : - Functions to find if a plumed object is valid
418 : (\ref plumed_valid(), \ref plumed_gvalid(), \ref PLMD::Plumed::valid(), and \ref PLMD::Plumed::gvalid()).
419 : - Functions to create a plumed object based on the path of a specific kernel
420 : (\ref plumed_create_dlopen() and \ref PLMD::Plumed::dlopen()).
421 : - Functions to create a plumed object referencing to another one, implementing a reference counter
422 : (\ref plumed_create_reference(), \ref plumed_create_reference_v(), \ref plumed_create_reference_f().
423 :
424 : */
425 :
426 :
427 : /* BEGINNING OF DECLARATIONS */
428 :
429 : /* SETTING DEFAULT VALUES FOR CONTROL MACROS */
430 :
431 : /*
432 : 1: make the C wrapper functions extern (default)
433 : 0: make the C wrapper functions static (C) or inline (C++)
434 :
435 : If set to zero, it disables all functions that only make sense as extern, such as
436 : Fortran wrappers, global objects, and plumed_kernel_register.
437 :
438 : It can be set to zero to include multiple copies of the wrapper implementation without worrying
439 : about duplicated symbols.
440 :
441 : Notice that C++ wrappers are always inline. What this function controls is if the C wrappers
442 : (called by the C++ wrappers) is inline or not. Also consider that if this header is compiled
443 : with C++ and inline C wrappers, the C wrappers will be actually compiled with C++ linkage
444 : in the root namespace.
445 :
446 : Used both in declarations (to know which functions to declare) and definitions (to know which functions to define).
447 : */
448 :
449 : #ifndef __PLUMED_WRAPPER_EXTERN
450 : #define __PLUMED_WRAPPER_EXTERN 1
451 : #endif
452 :
453 : /*
454 : 1: emit global plumed object and related functions (default)
455 : 0: do not emit global plumed object and related functions
456 :
457 : Used both in declarations (to know which functions to declare) and definitions (to know which functions to define).
458 : */
459 :
460 : #ifndef __PLUMED_WRAPPER_GLOBAL
461 : #define __PLUMED_WRAPPER_GLOBAL 1
462 : #endif
463 :
464 : /*
465 : 1: Enable typesafe C interface (default)
466 : 0: Disable typesafe C interface
467 :
468 : Only used in declarations. Requires C11 _Generic and variadic macros, and so it is
469 : disabled by default with C++ and pre C11 compilers.
470 :
471 : https://mort.coffee/home/c-compiler-quirks/
472 : */
473 :
474 : #ifndef __PLUMED_WRAPPER_C_TYPESAFE
475 : # if defined(__STDC_VERSION__)
476 : # if ! defined(__cplusplus) && __STDC_VERSION__ >= 201112L
477 : # if defined(__GNUC__) && !defined(__clang__)
478 : # if (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))
479 : # define __PLUMED_WRAPPER_C_TYPESAFE 1
480 : # endif
481 : # else
482 : # define __PLUMED_WRAPPER_C_TYPESAFE 1
483 : # endif
484 : # endif
485 : # endif
486 : # ifndef __PLUMED_WRAPPER_C_TYPESAFE
487 : # define __PLUMED_WRAPPER_C_TYPESAFE 0
488 : # endif
489 : #endif
490 :
491 : /*
492 : 1: Enable RTLD_DEEPBIND when possible (default)
493 : 0: Disable RTLD_DEEPBIND
494 : */
495 :
496 : #ifndef __PLUMED_WRAPPER_ENABLE_RTLD_DEEPBIND
497 : #define __PLUMED_WRAPPER_ENABLE_RTLD_DEEPBIND 1
498 : #endif
499 :
500 : /*
501 : 1: enable C++ wrapper (default)
502 : 0: disable C++ wrapper
503 :
504 : Only used in declarations, but affects the scope of the C interface also in definitions.
505 : */
506 :
507 : #ifndef __PLUMED_WRAPPER_CXX
508 : #define __PLUMED_WRAPPER_CXX 1
509 : #endif
510 :
511 : /*
512 : 1: new headers such as cstdlib are included in C++ (default)
513 : 0: old headers such as stdlib.h are included in C++
514 :
515 : Should only be set to zero when including the Plumed.h file in a file using the
516 : old (stdlib.h) convention.
517 :
518 : Used both in declarations and definitions.
519 : */
520 :
521 : #ifndef __PLUMED_WRAPPER_CXX_STD
522 : #define __PLUMED_WRAPPER_CXX_STD 1
523 : #endif
524 :
525 : /*
526 : 1: place C++ wrappers in an anonymous namespace
527 : 0: place C++ wrappers in the PLMD namespace (default)
528 :
529 : It will make PLMD::Plumed a different class (though with the same name)
530 : in each of the translation units in which `Plumed.h` is included.
531 :
532 : Can be used to completey separate C++ implementations. However, it will make
533 : it impossible to transfer Plumed objects between different translation units
534 : without converting to a void* or plumed object.
535 :
536 : Only used in declarations, but affects the scope of the C interface also in definitions.
537 : */
538 :
539 : #ifndef __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE
540 : #define __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE 0
541 : #endif
542 :
543 :
544 : /*
545 : 1: throw exceptions such as PLMD::Exception
546 : 0: throw exceptions such as PLMD::Plumed::Exception (default)
547 :
548 : This is useful when including Plumed.h within the plumed library
549 : in anonymous mode, to make sure that the exception types from the
550 : library are used.
551 : */
552 : #ifndef __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS
553 : #define __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS 0
554 : #endif
555 :
556 : /*
557 : 1: make PLMD::Plumed class polymorphic (default)
558 : 0: make PLMD::Plumed class non-polymorphic
559 :
560 : Only used in declarations.
561 : */
562 :
563 : #ifndef __PLUMED_WRAPPER_CXX_POLYMORPHIC
564 : #define __PLUMED_WRAPPER_CXX_POLYMORPHIC 1
565 : #endif
566 :
567 : /*
568 : 1: Forces strict mode for vector shapes
569 : 0: Enable backward compatible sloppy mode for vector shapes (default)
570 :
571 : Only used in declarations.
572 :
573 : */
574 : #ifndef __PLUMED_WRAPPER_CXX_DETECT_SHAPES_STRICT
575 : #define __PLUMED_WRAPPER_CXX_DETECT_SHAPES_STRICT 0
576 : #endif
577 :
578 : /*
579 : 1: Enable typesafe interface (default)
580 : 0: Disable typesafe interface
581 :
582 : Only used in declarations.
583 : */
584 :
585 : #ifndef __PLUMED_WRAPPER_CXX_BIND_C
586 : #define __PLUMED_WRAPPER_CXX_BIND_C 1
587 : #endif
588 :
589 : /*
590 : 1: Enable passing long long int
591 : 0: Disable passing long long int
592 :
593 : Only used in declarations. Default is 0 in C++<11 and 1 in C++>=11
594 : */
595 :
596 : #ifndef __PLUMED_WRAPPER_CXX_LONGLONG
597 : #if __cplusplus > 199711L
598 : #define __PLUMED_WRAPPER_CXX_LONGLONG 1
599 : #else
600 : #define __PLUMED_WRAPPER_CXX_LONGLONG 0
601 : #endif
602 : #endif
603 :
604 : /*
605 : 1: make the default constructor create an invalid object
606 : 0: make the default constructor create a valid object
607 :
608 : Only for internal usage.
609 : */
610 : #ifndef __PLUMED_WRAPPER_CXX_DEFAULT_INVALID
611 : #define __PLUMED_WRAPPER_CXX_DEFAULT_INVALID 0
612 : #endif
613 :
614 : /*
615 : Size of a buffer used to store message for exceptions with noexcept constructor.
616 : Should typically hold short messages. Anyway, as long as the stack size stays within the correct
617 : limits it does not seem to affect efficiency. Notice that there cannot be recursive calls of
618 : PLMD::Plumed::cmd, so that it should be in practice irrelevant.
619 : */
620 : #ifndef __PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER
621 : #define __PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER 512
622 : #endif
623 :
624 : /*
625 : 1: enable nested exceptions (only with C++11) (default)
626 : 0: disable nested exceptions
627 :
628 : For internal testing, used to mimic pre C++11 behavior on
629 : nested exception.
630 :
631 : Only used in declarations.
632 : */
633 :
634 : #ifndef __PLUMED_WRAPPER_CXX_ENABLE_NESTED_EXCEPTIONS
635 : #define __PLUMED_WRAPPER_CXX_ENABLE_NESTED_EXCEPTIONS 1
636 : #endif
637 :
638 : /*
639 : By default, assume C++11 compliant library is not available.
640 : */
641 :
642 : #ifndef __PLUMED_WRAPPER_LIBCXX11
643 : #define __PLUMED_WRAPPER_LIBCXX11 0
644 : #endif
645 :
646 : /*
647 : By default, assume C++17 compliant library is not available.
648 : */
649 :
650 : #ifndef __PLUMED_WRAPPER_LIBCXX17
651 : #define __PLUMED_WRAPPER_LIBCXX17 0
652 : #endif
653 :
654 : /* The following macros are just to define shortcuts */
655 :
656 : /* This is needed to use non c-style cast when working in c++ */
657 : #ifdef __cplusplus
658 : #define __PLUMED_WRAPPER_STATIC_CAST(to,what) static_cast<to>(what)
659 : #define __PLUMED_WRAPPER_REINTERPRET_CAST(to,what) reinterpret_cast<to>(what)
660 : #else
661 : #define __PLUMED_WRAPPER_STATIC_CAST(to,what) ((to) what)
662 : #define __PLUMED_WRAPPER_REINTERPRET_CAST(to,what) __PLUMED_WRAPPER_STATIC_CAST(to,what)
663 : #endif
664 :
665 : /* Simplify addition of extern "C" blocks. */
666 : #ifdef __cplusplus
667 : #define __PLUMED_WRAPPER_EXTERN_C_BEGIN extern "C" {
668 : #define __PLUMED_WRAPPER_EXTERN_C_END }
669 : #else
670 : #define __PLUMED_WRAPPER_EXTERN_C_BEGIN
671 : #define __PLUMED_WRAPPER_EXTERN_C_END
672 : #endif
673 :
674 : /* Without C++, stdlib functions should not be prepended with ::std:: */
675 : #ifndef __cplusplus
676 : #undef __PLUMED_WRAPPER_CXX_STD
677 : #define __PLUMED_WRAPPER_CXX_STD 0
678 : #endif
679 :
680 : /* Set prefix for stdlib functions */
681 : #if __PLUMED_WRAPPER_CXX_STD
682 : #define __PLUMED_WRAPPER_STD ::std::
683 : #else
684 : #define __PLUMED_WRAPPER_STD
685 : #endif
686 :
687 : /* Allow using noexcept, explicit, and override with C++11 compilers */
688 : #ifdef __cplusplus /*{*/
689 : #if __cplusplus > 199711L
690 : #define __PLUMED_WRAPPER_CXX_NOEXCEPT noexcept
691 : #define __PLUMED_WRAPPER_CXX_NORETURN [[ noreturn ]]
692 : #define __PLUMED_WRAPPER_CXX_EXPLICIT explicit
693 : #define __PLUMED_WRAPPER_CXX_OVERRIDE override
694 : #define __PLUMED_WRAPPER_CXX_NULLPTR nullptr
695 : #else
696 : #define __PLUMED_WRAPPER_CXX_NOEXCEPT throw()
697 : #define __PLUMED_WRAPPER_CXX_NORETURN
698 : #define __PLUMED_WRAPPER_CXX_EXPLICIT
699 : #define __PLUMED_WRAPPER_CXX_OVERRIDE
700 : #define __PLUMED_WRAPPER_CXX_NULLPTR NULL
701 : #endif
702 : #else
703 : #define __PLUMED_WRAPPER_CXX_NOEXCEPT
704 : #define __PLUMED_WRAPPER_CXX_NORETURN
705 : #define __PLUMED_WRAPPER_CXX_EXPLICIT
706 : #define __PLUMED_WRAPPER_CXX_OVERRIDE
707 : #define __PLUMED_WRAPPER_CXX_NULLPTR NULL
708 : #endif /*}*/
709 :
710 : /* static inline, for to avoid compiler warnings */
711 : #if defined(__cplusplus) || __STDC_VERSION__>=199901L
712 : #define __PLUMED_WRAPPER_STATIC_INLINE static inline
713 : #else
714 : #define __PLUMED_WRAPPER_STATIC_INLINE static
715 : #endif
716 :
717 : /* Macros for anonymous namespace */
718 : #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE && defined(__cplusplus) /*{*/
719 : #define __PLUMED_WRAPPER_ANONYMOUS_BEGIN namespace {
720 : #define __PLUMED_WRAPPER_ANONYMOUS_END }
721 : #else
722 : #define __PLUMED_WRAPPER_ANONYMOUS_BEGIN
723 : #define __PLUMED_WRAPPER_ANONYMOUS_END
724 : #endif /*}*/
725 :
726 : #if __PLUMED_WRAPPER_EXTERN /*{*/
727 :
728 : #define __PLUMED_WRAPPER_C_BEGIN __PLUMED_WRAPPER_EXTERN_C_BEGIN extern
729 : #define __PLUMED_WRAPPER_C_END __PLUMED_WRAPPER_EXTERN_C_END
730 : #define __PLUMED_WRAPPER_INTERNALS_BEGIN __PLUMED_WRAPPER_EXTERN_C_BEGIN static
731 : #define __PLUMED_WRAPPER_INTERNALS_END __PLUMED_WRAPPER_EXTERN_C_END
732 :
733 : #else
734 :
735 : #ifdef __cplusplus
736 : #define __PLUMED_WRAPPER_C_BEGIN __PLUMED_WRAPPER_ANONYMOUS_BEGIN inline
737 : #define __PLUMED_WRAPPER_C_END __PLUMED_WRAPPER_ANONYMOUS_END
738 : #else
739 : #define __PLUMED_WRAPPER_C_BEGIN __PLUMED_WRAPPER_STATIC_INLINE
740 : #define __PLUMED_WRAPPER_C_END
741 : #endif
742 :
743 : #define __PLUMED_WRAPPER_INTERNALS_BEGIN __PLUMED_WRAPPER_C_BEGIN
744 : #define __PLUMED_WRAPPER_INTERNALS_END __PLUMED_WRAPPER_C_END
745 :
746 : /* with an not-external interface, it does not make sense to define global functions */
747 : #undef __PLUMED_WRAPPER_GLOBAL
748 : #define __PLUMED_WRAPPER_GLOBAL 0
749 :
750 : #endif /*}*/
751 :
752 : #if __PLUMED_WRAPPER_CXX_STD
753 : #include <cstddef> /* size_t */
754 : #include <cstring> /* memcpy */
755 : #include <cstdio> /* fprintf */
756 : #include <cstdlib> /* abort */
757 : #include <cassert> /* assert */
758 : #else
759 : #include <stddef.h>
760 : #include <string.h>
761 : #include <stdio.h> /* FILE and fprintf */
762 : #include <stdlib.h> /* abort */
763 : #include <limits.h> /* CHAR_MIN */
764 : #include <assert.h> /* assert */
765 : #endif
766 :
767 : /**
768 : This is an internal tool, to make sure that all malloc calls inside the
769 : plumed library refer to the same implementation. When compiling with
770 : __PLUMED_WRAPPER_DEBUG_REFCOUNT=1 it is possible to log
771 : allocations and deallocations, so as to debug the wrappers.
772 : */
773 : __PLUMED_WRAPPER_C_BEGIN
774 : void* plumed_malloc(__PLUMED_WRAPPER_STD size_t size);
775 : __PLUMED_WRAPPER_C_END
776 :
777 : /**
778 : This is an internal tool, to make sure that all free calls inside the
779 : plumed library refer to the same implementation. When compiling with
780 : __PLUMED_WRAPPER_DEBUG_REFCOUNT=1 it is possible to log
781 : allocations and deallocations, so as to debug the wrappers.
782 : */
783 : __PLUMED_WRAPPER_C_BEGIN
784 : void plumed_free(void* ptr);
785 : __PLUMED_WRAPPER_C_END
786 :
787 : /**
788 : \brief Main plumed object
789 :
790 : This is an object containing a Plumed instance, which should be used in
791 : the MD engine. It should first be initialized with plumed_create(),
792 : then it communicates with the MD engine using plumed_cmd(). Finally,
793 : before the termination, it should be deallocated with plumed_finalize().
794 : Its interface is very simple and general, and is expected
795 : not to change across plumed versions. See \ref ReferencePlumedH.
796 : */
797 : typedef struct {
798 : /**
799 : \private
800 : \brief Void pointer holding the real PlumedMain structure
801 :
802 : To maintain binary compatibility, we should not add members to this structure.
803 : As of PLUMED 2.5, in order to add new components we do not store the pointer
804 : to \ref PlumedMain here but rather a pointer to an intermediate private structure
805 : that contains all the details.
806 : */
807 : void*p;
808 : } plumed;
809 :
810 : typedef struct {
811 : void* ptr;
812 : void (*handler)(void*,int,const char*,const void*);
813 : } plumed_nothrow_handler;
814 :
815 : /** \relates plumed
816 : \brief Structure holding a typesafe pointer.
817 : */
818 :
819 : typedef struct {
820 : /** Pointer to data */
821 : const void* ptr;
822 : /** Number of elements (in case pointing to an array) */
823 : __PLUMED_WRAPPER_STD size_t nelem;
824 : /** Shape (scanned up to a zero value is found) */
825 : const __PLUMED_WRAPPER_STD size_t* shape;
826 : /**
827 : sum of:
828 : sizeof(pointed data), up to 0x10000 (65536). 0 means size not checked
829 : 0x10000 * data type, up to 0xff (255)
830 : 0 not typechecked
831 : 1 void
832 : 2 nullptr
833 : 3 integral
834 : 4 floating point
835 : 5 FILE (size will not be computed as it might be incomplete)
836 : >5 not typechecked, reserved for future extensions
837 : 0x1000000 * 1 for unsigned (ignored)
838 : 0x2000000 * pointer/const type, up to 8
839 : 0 not typechecked
840 : 1 T (pass-by-value)
841 : 2 T *
842 : 3 T const *
843 : 4 T * *
844 : 5 T * const *
845 : 6 T const * *
846 : 7 T const * const *
847 : 0x10000000 * 1 to forbid pointer copy (pointer copy is also forbidden for pass-by-value)
848 : 0x20000000 and higher bits are ignored, reserved for future extensions
849 : */
850 : __PLUMED_WRAPPER_STD size_t flags;
851 : /** Optional information, not used yet */
852 : const void* opt;
853 : } plumed_safeptr;
854 :
855 : /* local structure */
856 : typedef struct plumed_error_filesystem_path {
857 : __PLUMED_WRAPPER_STD size_t numbytes;
858 : void* ptr;
859 : } plumed_error_filesystem_path;
860 :
861 : /**
862 : Small structure that is only defined locally to retrieve errors.
863 :
864 : It is supposed to be used in the C11/C++ plumed_cmd interface as follows:
865 : \verbatim
866 : plumed p;
867 : plumed_error error;
868 :
869 : p=plumed_create();
870 :
871 : plumed_cmd(p,"setNatoms",10,&error);
872 : if(error.code) {
873 : fprintf(errors,"%d\n",error.code);
874 : plumed_error_finalize(error); // make sure the error object is finalized!
875 : }
876 : // if no error was raised (error.code==0), it is not necessary to call plumed_error_finalize.
877 : // but doing it is harmless
878 :
879 : // no need to initialize error, it is written in the plumed_cmd function
880 : plumed_cmd(p,"init",&error);
881 : if(error.code) {
882 : fprintf(errors,"%d\n",error.code);
883 : plumed_error_finalize(error); // make sure the error object is finalized!
884 : }
885 : \endverbatim
886 :
887 : The layout of this structure is subject to change, thus all the functions manipulating it
888 : are defined as inline/static functions. In the future, we might reach some form
889 : of ABI stability, and these functions might be moved below to the implementation
890 : file.
891 :
892 : Notice that there is a macro plumed_error() defined in the PLUMED source code
893 : (at tools/Exception.h). There is no conflict with this type since C preprocessor
894 : distinguishes macros and function-like macros.
895 : */
896 : typedef struct plumed_error {
897 : /** code used for translating messages */
898 : int code;
899 : /** error code for system_error */
900 : int error_code;
901 : /** category - for errors */
902 : int error_category;
903 : /** path1 - for filesystem_error */
904 : plumed_error_filesystem_path path1;
905 : /** path2 - for filesystem_error */
906 : plumed_error_filesystem_path path2;
907 : /** message */
908 : const char* what;
909 : /** the buffer containing the message to be deallocated */
910 : char* what_buffer;
911 : /** pointer to nested exception */
912 : struct plumed_error* nested;
913 : } plumed_error;
914 :
915 : /** Initialize error (for internal usage) */
916 : __PLUMED_WRAPPER_STATIC_INLINE void plumed_error_init(plumed_error* error) __PLUMED_WRAPPER_CXX_NOEXCEPT {
917 : assert(error);
918 16675 : error->code=0;
919 16675 : error->error_code=0;
920 16675 : error->error_category=0;
921 16675 : error->path1.numbytes=0;
922 16675 : error->path1.ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
923 16675 : error->path2.numbytes=0;
924 16675 : error->path2.ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
925 16675 : error->what=__PLUMED_WRAPPER_CXX_NULLPTR;
926 16675 : error->what_buffer=__PLUMED_WRAPPER_CXX_NULLPTR;
927 16675 : error->nested=__PLUMED_WRAPPER_CXX_NULLPTR;
928 : }
929 :
930 : /** Finalize error - should be called when an error is raised to avoid leaks */
931 : /* cppcheck-suppress passedByValue */
932 0 : __PLUMED_WRAPPER_STATIC_INLINE void plumed_error_finalize(plumed_error error) __PLUMED_WRAPPER_CXX_NOEXCEPT {
933 0 : if(!error.code) {
934 : return;
935 : }
936 0 : if(error.nested) {
937 0 : plumed_error_finalize(*error.nested);
938 0 : plumed_free(error.nested);
939 : }
940 0 : if(error.path1.ptr) {
941 0 : plumed_free(error.path1.ptr);
942 : }
943 0 : if(error.path2.ptr) {
944 0 : plumed_free(error.path2.ptr);
945 : }
946 0 : if(error.what_buffer) {
947 0 : plumed_free(error.what_buffer);
948 : }
949 : }
950 :
951 : /** Access message - more robust than directly accessing what ptr, for future extensibility */
952 : /* cppcheck-suppress passedByValue */
953 : __PLUMED_WRAPPER_STATIC_INLINE const char* plumed_error_what(plumed_error error) __PLUMED_WRAPPER_CXX_NOEXCEPT {
954 : return error.what;
955 : }
956 :
957 : /** Set error to bad_alloc (for internal usage).
958 : At variance with plumed_error_init, it also finalizes the error, possibly
959 : deallocating any buffer.
960 : */
961 0 : __PLUMED_WRAPPER_STATIC_INLINE void plumed_error_set_bad_alloc(plumed_error*error) {
962 : assert(error);
963 0 : plumed_error_finalize(*error);
964 : plumed_error_init(error);
965 0 : error->what="[msg erased due to allocation failure]";
966 0 : error->code=11400;
967 0 : }
968 :
969 : /** Recursive merge (for internal usage) */
970 : __PLUMED_WRAPPER_STATIC_INLINE void plumed_error_recursive_merge(plumed_error* error,char*buffer,const char*join,__PLUMED_WRAPPER_STD size_t*len) __PLUMED_WRAPPER_CXX_NOEXCEPT {
971 : if(error->nested) {
972 : plumed_error_recursive_merge(error->nested,buffer,join,len);
973 : }
974 : __PLUMED_WRAPPER_STD strncat(buffer,plumed_error_what(*error),*len);
975 : *len -= __PLUMED_WRAPPER_STD strlen(plumed_error_what(*error));
976 : __PLUMED_WRAPPER_STD strncat(buffer,join,*len);
977 : *len -= __PLUMED_WRAPPER_STD strlen(join);
978 : }
979 :
980 : /** Merge with nested exceptions */
981 : __PLUMED_WRAPPER_STATIC_INLINE void plumed_error_merge_with_nested(plumed_error* error) __PLUMED_WRAPPER_CXX_NOEXCEPT {
982 : __PLUMED_WRAPPER_STD size_t len;
983 : __PLUMED_WRAPPER_STD size_t len_join;
984 : /* The is temporarily holding the new message */
985 : char* new_buffer;
986 : /* This is the string used to concatenate messages */
987 : const char* join="\n\nThe above exception was the direct cause of the following exception:\n";
988 : /* This is used to iterate over the linked list of nested exceptions */
989 : plumed_error*e;
990 :
991 : /* If exception is not nested, nothing to do */
992 : if(!error->nested) {
993 : return;
994 : }
995 :
996 : /* Accumulate the total length of the concatenated message */
997 : len_join=__PLUMED_WRAPPER_STD strlen(join);
998 : e=error;
999 : len=__PLUMED_WRAPPER_STD strlen(plumed_error_what(*e));
1000 : while(e->nested) {
1001 : e=e->nested;
1002 : len+=len_join+__PLUMED_WRAPPER_STD strlen(plumed_error_what(*e));
1003 : }
1004 :
1005 : /* Allocate the new message */
1006 : new_buffer=__PLUMED_WRAPPER_STATIC_CAST(char*, plumed_malloc(len+1));
1007 : if(new_buffer) {
1008 : /* If allocation was successful, merge the messages */
1009 : new_buffer[0]='\0';
1010 : /* Notice that we have a forward linked list but we need to go through that in backward order
1011 : (inner to outer). To do that without allocating an additional array, we use a recursive
1012 : function.
1013 : */
1014 : assert(error->nested);
1015 : plumed_error_recursive_merge(error->nested,new_buffer,join,&len);
1016 : __PLUMED_WRAPPER_STD strncat(new_buffer,plumed_error_what(*error),len);
1017 : len -= __PLUMED_WRAPPER_STD strlen(plumed_error_what(*error));
1018 : /* we keep track of length of buffer for safety */
1019 : assert(len==0);
1020 : }
1021 : error->what=new_buffer;
1022 :
1023 : /* Deallocate the previous message */
1024 : if(error->what_buffer) {
1025 : plumed_free(error->what_buffer);
1026 : }
1027 : error->what_buffer=new_buffer;
1028 :
1029 : /* Finalize the chain of nested exceptions */
1030 : plumed_error_finalize(*error->nested);
1031 : plumed_free(error->nested);
1032 : error->nested=__PLUMED_WRAPPER_CXX_NULLPTR;
1033 :
1034 : if(!error->what) {
1035 : /* If allocation was not successful, reset to bad_alloc */
1036 : plumed_error_set_bad_alloc(error);
1037 : }
1038 : }
1039 :
1040 : /** Rethrow error (calling abort) */
1041 : __PLUMED_WRAPPER_CXX_NORETURN __PLUMED_WRAPPER_STATIC_INLINE void plumed_error_rethrow(plumed_error h) {
1042 : if(h.nested) {
1043 : plumed_error_merge_with_nested(&h);
1044 : }
1045 : __PLUMED_WRAPPER_STD fprintf(stderr,"Terminate due to exception. Code: %d\n%s\n",h.code,plumed_error_what(h));
1046 : __PLUMED_WRAPPER_STD abort();
1047 : }
1048 :
1049 : /** Callback (for internal usage) */
1050 0 : __PLUMED_WRAPPER_STATIC_INLINE void plumed_error_set(void*ptr,int code,const char*what,const void* opt) __PLUMED_WRAPPER_CXX_NOEXCEPT {
1051 : plumed_error* error;
1052 : __PLUMED_WRAPPER_STD size_t len;
1053 : void*const* options;
1054 : plumed_error_filesystem_path path;
1055 :
1056 : error=__PLUMED_WRAPPER_STATIC_CAST(plumed_error*, ptr);
1057 :
1058 0 : error->code=code;
1059 0 : error->error_code=0;
1060 0 : len=__PLUMED_WRAPPER_STD strlen(what);
1061 0 : error->what_buffer=__PLUMED_WRAPPER_STATIC_CAST(char*, plumed_malloc(len+1));
1062 0 : if(!error->what_buffer) {
1063 0 : plumed_error_set_bad_alloc(error);
1064 0 : return;
1065 : }
1066 :
1067 : __PLUMED_WRAPPER_STD strncpy(error->what_buffer,what,len+1);
1068 0 : error->what=error->what_buffer;
1069 :
1070 : /* interpret optional arguments */
1071 0 : if(opt) {
1072 : options=__PLUMED_WRAPPER_STATIC_CAST(void*const*, opt);
1073 0 : while(*options) {
1074 : /* c: error code */
1075 0 : if(*(__PLUMED_WRAPPER_STATIC_CAST(const char*,*options))=='c' && *(options+1)) {
1076 0 : error->error_code=*(__PLUMED_WRAPPER_STATIC_CAST(const int*,*(options+1)));
1077 0 : break;
1078 : }
1079 0 : options+=2;
1080 : }
1081 :
1082 : options=__PLUMED_WRAPPER_STATIC_CAST(void*const*,opt);
1083 0 : while(*options) {
1084 : /* C: error_category */
1085 0 : if(*(__PLUMED_WRAPPER_STATIC_CAST(char*, *options))=='C' && *(options+1)) {
1086 0 : error->error_category=*(__PLUMED_WRAPPER_STATIC_CAST(const int*,*(options+1)));
1087 0 : break;
1088 : }
1089 0 : options+=2;
1090 : }
1091 :
1092 : options=__PLUMED_WRAPPER_STATIC_CAST(void*const*, opt);
1093 0 : while(*options) {
1094 : /* path 1 */
1095 0 : if(*(__PLUMED_WRAPPER_STATIC_CAST(char*, *options))=='p' && *(options+1)) {
1096 0 : path=*__PLUMED_WRAPPER_STATIC_CAST(plumed_error_filesystem_path*,*(options+1));
1097 0 : error->path1.ptr=plumed_malloc(path.numbytes);
1098 0 : if(!error->path1.ptr) {
1099 0 : plumed_error_set_bad_alloc(error);
1100 0 : return;
1101 : }
1102 0 : error->path1.numbytes=path.numbytes;
1103 : __PLUMED_WRAPPER_STD memcpy(error->path1.ptr,path.ptr,path.numbytes);
1104 : break;
1105 : }
1106 0 : options+=2;
1107 : }
1108 :
1109 : options=__PLUMED_WRAPPER_STATIC_CAST(void*const*, opt);
1110 0 : while(*options) {
1111 : /* path 2 */
1112 0 : if(*(__PLUMED_WRAPPER_STATIC_CAST(char*, *options))=='q' && *(options+1)) {
1113 0 : path=*__PLUMED_WRAPPER_STATIC_CAST(plumed_error_filesystem_path*,*(options+1));
1114 0 : error->path2.ptr=plumed_malloc(path.numbytes);
1115 0 : if(!error->path2.ptr) {
1116 0 : plumed_error_set_bad_alloc(error);
1117 0 : return;
1118 : }
1119 0 : error->path2.numbytes=path.numbytes;
1120 : __PLUMED_WRAPPER_STD memcpy(error->path2.ptr,path.ptr,path.numbytes);
1121 : break;
1122 : }
1123 0 : options+=2;
1124 : }
1125 :
1126 : options=__PLUMED_WRAPPER_STATIC_CAST(void*const*, opt);
1127 0 : while(*options) {
1128 : /* n: nested exception */
1129 0 : if(*(__PLUMED_WRAPPER_STATIC_CAST(char*, *options))=='n' && *(options+1)) {
1130 : /* notice that once this is allocated it is guaranteed to be deallocated by the recursive destructor */
1131 0 : error->nested=__PLUMED_WRAPPER_STATIC_CAST(plumed_error*, plumed_malloc(sizeof(plumed_error)));
1132 : /* this is if malloc fails */
1133 0 : if(!error->nested) {
1134 0 : plumed_error_set_bad_alloc(error);
1135 0 : break;
1136 : }
1137 : plumed_error_init(__PLUMED_WRAPPER_STATIC_CAST(plumed_error*,error->nested));
1138 : /* plumed will make sure to only use this if it is not null */
1139 0 : *__PLUMED_WRAPPER_STATIC_CAST(void**,*(options+1))=error->nested;
1140 0 : break;
1141 : }
1142 0 : options+=2;
1143 : }
1144 : }
1145 : }
1146 :
1147 : /** \relates plumed
1148 : \brief Constructor
1149 :
1150 : Constructs a plumed object.
1151 :
1152 : Notice that if you are linking against libplumedWrapper.a, if you are
1153 : using a code patched in runtime mode, or if you are including the `Plumed.c`
1154 : file directly in your code, this constructor might return an invalid plumed
1155 : object. In particular, this could happen if the `PLUMED_KERNEL` environment
1156 : variable is not set or set incorrectly. In order to detect an incorrect
1157 : plumed object you might use \ref plumed_valid() on the resulting object.
1158 : Alternatively, if you use \ref plumed_cmd() on an invalid plumed object the code will exit.
1159 : Also notice that to avoid memory leaks you should call \ref plumed_finalize()
1160 : to finalize a plumed object even if it is invalid:
1161 : \verbatim
1162 : plumed p=plumed_create();
1163 : if(!plumed_valid(p)) {
1164 : // this will happen if the PLUMED_KERNEL variable is not set correctly
1165 : plumed_finalize(p);
1166 : return whatever;
1167 : }
1168 : \endverbatim
1169 :
1170 : \return The constructed plumed object
1171 : */
1172 : __PLUMED_WRAPPER_C_BEGIN
1173 : plumed plumed_create(void);
1174 : __PLUMED_WRAPPER_C_END
1175 :
1176 : /** \relates plumed
1177 : \brief Constructor from path. Available as of PLUMED 2.5
1178 :
1179 : It tries to construct a plumed object loading the kernel located at path.
1180 : Notice that it could leave the resulting object in an invalid state.
1181 : In order to detect an invalid
1182 : plumed object you might use \ref plumed_valid() on the resulting object.
1183 : Alternatively, if you use \ref plumed_cmd() on an invalid plumed object the code will exit.
1184 :
1185 : Also notice that to avoid memory leaks you should call \ref plumed_finalize()
1186 : to finalize a plumed object even if it is invalid.
1187 : \verbatim
1188 : plumed p=plumed_create(path);
1189 : if(!plumed_valid(p)) {
1190 : // this will happen if the path argument is not set correctly
1191 : plumed_finalize(p);
1192 : return whatever;
1193 : }
1194 : \endverbatim
1195 :
1196 : \return The constructed plumed object
1197 : */
1198 : __PLUMED_WRAPPER_C_BEGIN
1199 : plumed plumed_create_dlopen(const char*path);
1200 : __PLUMED_WRAPPER_C_END
1201 :
1202 :
1203 : /**
1204 : \brief Constructor from path. Available as of PLUMED 2.5
1205 :
1206 : Same as \ref plumed_create_dlopen, but also allows to specify the mode for dlopen.
1207 :
1208 : \warning
1209 : Use with care, since not all the possible modes work correctly with PLUMED.
1210 : */
1211 : __PLUMED_WRAPPER_C_BEGIN
1212 : plumed plumed_create_dlopen2(const char*path,int mode);
1213 : __PLUMED_WRAPPER_C_END
1214 :
1215 : /**
1216 : \brief Constructor from dlopen handle. Available as of PLUMED 2.8
1217 :
1218 : Same as \ref plumed_create_dlopen, but it acts on an already loaded library.
1219 : This allows to separate the library loading from the construction of the
1220 : plumed object. By using this function, the caller takes the responsibility
1221 : to later use dlclose on this handle.
1222 : */
1223 : __PLUMED_WRAPPER_C_BEGIN
1224 : plumed plumed_create_dlsym(void* dlhandle);
1225 : __PLUMED_WRAPPER_C_END
1226 :
1227 : /** \relates plumed
1228 : Create a new reference to an existing object, increasing its reference count. Available as of PLUMED 2.5
1229 :
1230 : Use it to increase by one the reference count of a plumed object.
1231 : The resulting pointer might be identical to the one passed as an
1232 : argument, but the reference count will be incremented by one.
1233 : Notice that you should finalize the resulting object.
1234 : \verbatim
1235 : plumed p1;
1236 : plumed p2;
1237 : p1=plumed_create();
1238 : p2=plumed_create_reference(p1);
1239 : plumed_finalize(p1);
1240 : // now you can still use p2
1241 : plumed_cmd(p2,"init",NULL);
1242 : plumed_finalize(p2);
1243 : // now the underlying object is destroyed.
1244 : \endverbatim
1245 :
1246 : If the `p` object is invalid, also the returned object will be invalid.
1247 :
1248 : \param p The plumed object that will be referenced to.
1249 : \return The constructed plumed object
1250 : */
1251 :
1252 : __PLUMED_WRAPPER_C_BEGIN
1253 : plumed plumed_create_reference(plumed p);
1254 : __PLUMED_WRAPPER_C_END
1255 :
1256 : /** \relates plumed
1257 : \brief Create a new reference to an existing object passed as a void pointer, increasing its reference count. Available as of PLUMED 2.5
1258 :
1259 : \return The constructed plumed object
1260 : */
1261 :
1262 : __PLUMED_WRAPPER_C_BEGIN
1263 : plumed plumed_create_reference_v(void*v);
1264 : __PLUMED_WRAPPER_C_END
1265 :
1266 : /** \relates plumed
1267 : \brief Create a new reference to an existing object passed as a fortran string, increasing its reference count. Available as of PLUMED 2.5
1268 :
1269 : \return The constructed plumed object
1270 : */
1271 :
1272 : __PLUMED_WRAPPER_C_BEGIN
1273 : plumed plumed_create_reference_f(const char*f);
1274 : __PLUMED_WRAPPER_C_END
1275 :
1276 : /** \relates plumed
1277 : \brief Constructor as invalid. Available as of PLUMED 2.5
1278 :
1279 : Can be used to create an object in the same state as if it was returned by
1280 : plumed_create_dlopen with an incorrect path (or plumed_create using runtime binding
1281 : and an incorrect PLUMED_KERNEL).
1282 :
1283 : Can be used to initialize a plumed object to a well-defined state without explicitly
1284 : creating it. The resulting object can be checked later with \ref plumed_valid.
1285 : Consider the following example
1286 : \verbatim
1287 : plumed p;
1288 : p=plumed_create_invalid();
1289 : // at this point p is initialized to a well-defined (invalid) state.
1290 : setenv("PLUMED_KERNEL","/path/to/kernel/libplumedKernel.so",1);
1291 : plumed_finalize(p);
1292 : p=plumed_create();
1293 : \endverbatim
1294 :
1295 : \return The constructed plumed object
1296 : */
1297 :
1298 : __PLUMED_WRAPPER_C_BEGIN
1299 : plumed plumed_create_invalid();
1300 : __PLUMED_WRAPPER_C_END
1301 :
1302 : /** \relates plumed
1303 : \brief Tells p to execute a command.
1304 :
1305 : If the object is not valid (see \ref plumed_valid), this command will exit.
1306 :
1307 : \param p The plumed object on which command is acting
1308 : \param key The name of the command to be executed
1309 : \param val The argument. It is declared as const to allow calls like plumed_cmd(p,"A","B"),
1310 : but for some choice of key it can change the content.
1311 :
1312 : Notice that within PLUMED we use a const_cast to remove any const qualifier from the second
1313 : argument of \ref plumed_cmd.
1314 :
1315 : In some cases val can be omitted: just pass a NULL pointer (in C++, val is optional and can be omitted,
1316 : or you can equivalently pass NULL or nullptr).
1317 : The set of possible keys is the real API of the plumed library, and will be expanded with time.
1318 : New commands will be added, but backward compatibility will be retained as long as possible.
1319 : */
1320 :
1321 : __PLUMED_WRAPPER_C_BEGIN
1322 : void plumed_cmd(plumed p,const char*key,const void*val);
1323 : __PLUMED_WRAPPER_C_END
1324 :
1325 : /**
1326 : \relates plumed
1327 : \brief Same as \ref plumed_cmd, but does not throw exceptions.
1328 :
1329 : This function is meant to be used when errors should be handled explicitly.
1330 : if an exception is raised within PLUMED, the function nothrow.handler() will
1331 : be called with arguments (nothrow.ptr,code,message,opt). This allows the C++ interface
1332 : to correctly rethrow exceptions, but might be used from C as well. opt can be used
1333 : to pass further information (not used yet).
1334 : */
1335 :
1336 : __PLUMED_WRAPPER_C_BEGIN
1337 : void plumed_cmd_nothrow(plumed p,const char*key,const void*val,plumed_nothrow_handler nothrow);
1338 : __PLUMED_WRAPPER_C_END
1339 :
1340 : __PLUMED_WRAPPER_C_BEGIN
1341 : void plumed_cmd_safe_nothrow(plumed p,const char*key,plumed_safeptr,plumed_nothrow_handler nothrow);
1342 : __PLUMED_WRAPPER_C_END
1343 :
1344 : __PLUMED_WRAPPER_C_BEGIN
1345 : void plumed_cmd_safe(plumed p,const char*key,plumed_safeptr);
1346 : __PLUMED_WRAPPER_C_END
1347 :
1348 : /** \relates plumed
1349 : \brief Destructor.
1350 :
1351 : It must be used for any object created using \ref plumed_create(),
1352 : even if the created object is not valid.
1353 :
1354 : \param p The plumed object to be deallocated
1355 : */
1356 :
1357 : __PLUMED_WRAPPER_C_BEGIN
1358 : void plumed_finalize(plumed p);
1359 : __PLUMED_WRAPPER_C_END
1360 :
1361 : /** \relates plumed
1362 : \brief Check if plumed is installed (for runtime binding).
1363 :
1364 : Notice that this is equivalent to creating a dummy object and checking if it is valid.
1365 :
1366 : \verbatim
1367 : // this:
1368 : //int a=plumed_installed();
1369 : // is equivalent to this:
1370 :
1371 : plumed p=plumed_create();
1372 : int a=plumed_valid(p);
1373 : plumed_finalize(p);
1374 :
1375 : \endverbatim
1376 :
1377 : This function is mostly provided for compatibility with PLUMED 2.4, where \ref plumed_valid()
1378 : was not available. Using \ref plumed_valid() is now preferred since it creates a single object
1379 : instead of creating a dummy object that is then discarded.
1380 :
1381 : \return 1 if plumed is installed, 0 otherwise
1382 : */
1383 :
1384 : __PLUMED_WRAPPER_C_BEGIN
1385 : int plumed_installed(void);
1386 : __PLUMED_WRAPPER_C_END
1387 :
1388 : /** \relates plumed
1389 : \brief Check if plumed object is valid. Available as of PLUMED 2.5
1390 :
1391 : It might return false if plumed is not available at runtime.
1392 :
1393 : \return 1 if plumed is valid, 0 otherwise
1394 : */
1395 :
1396 : __PLUMED_WRAPPER_C_BEGIN
1397 : int plumed_valid(plumed p);
1398 : __PLUMED_WRAPPER_C_END
1399 :
1400 : /** \relates plumed
1401 : \brief Returns the number of references to the underlying object. Available as of PLUMED 2.5.
1402 : */
1403 :
1404 : __PLUMED_WRAPPER_C_BEGIN
1405 : int plumed_use_count(plumed p);
1406 : __PLUMED_WRAPPER_C_END
1407 :
1408 :
1409 : /* routines to convert char handler from/to plumed objects */
1410 :
1411 : /** \related plumed
1412 : \brief Converts a C handler to a FORTRAN handler
1413 :
1414 : \param p The C handler
1415 : \param c The FORTRAN handler (a char[32])
1416 :
1417 : This function can be used to convert a plumed object created in C to
1418 : a plumed handler that can be used in FORTRAN. Notice that the reference counter
1419 : is not incremented. In other words, the FORTRAN object will be a weak reference.
1420 : If you later finalize the C handler, the FORTRAN handler will be invalid.
1421 : \verbatim
1422 : #include <plumed/wrapper/Plumed.h>
1423 : int main(int argc,char*argv[]){
1424 : plumed p;
1425 : p=plumed_create();
1426 : char fortran_handler[32];
1427 : plumed_c2f(p,fortran_handler);
1428 : printf("DEBUG: this is a string representation for the plumed handler: %s\n",fortran_handler);
1429 : fortran_routine(fortran_handler);
1430 : plumed_finalize(p);
1431 : return 0;
1432 : }
1433 : \endverbatim
1434 : Here `fortran_routine` is a routine implemented in FORTRAN that manipulates the
1435 : fortran_handler.
1436 : */
1437 :
1438 : __PLUMED_WRAPPER_C_BEGIN
1439 : void plumed_c2f(plumed p,char* c);
1440 : __PLUMED_WRAPPER_C_END
1441 :
1442 : /** \related plumed
1443 : \brief Converts a FORTRAN handler to a C handler
1444 : \param c The FORTRAN handler (a char[32])
1445 : \return The C handler
1446 :
1447 : This function can be used to convert a plumed object created in FORTRAN
1448 : to a plumed handler that can be used in C. Notice that the reference counter
1449 : is not incremented. In other words, the C object will be a weak reference.
1450 : If you later finalize the FORTRAN handler, the C handler will be invalid.
1451 : \verbatim
1452 : void c_routine(char handler[32]){
1453 : plumed p;
1454 : p=plumed_f2c(handler);
1455 : plumed_cmd(p,"init",NULL);
1456 : }
1457 : \endverbatim
1458 : Here `c_routine` is a C function that can be called from FORTRAN
1459 : and interact with the provided plumed handler.
1460 : */
1461 :
1462 : __PLUMED_WRAPPER_C_BEGIN
1463 : plumed plumed_f2c(const char* c);
1464 : __PLUMED_WRAPPER_C_END
1465 :
1466 : /** \related plumed
1467 : \brief Converts a plumed object to a void pointer. Available as of PLUMED 2.5.
1468 :
1469 : It returns a void pointer that can be converted back to a plumed object using \ref plumed_v2c.
1470 : When compiling without NDEBUG, it checks if the plumed object was properly created.
1471 : Notice that an invalid object (see \ref plumed_valid) can be converted to void* and back.
1472 :
1473 : Can be used to store a reference to a plumed object without including the Plumed.h header.
1474 : */
1475 :
1476 : __PLUMED_WRAPPER_C_BEGIN
1477 : void* plumed_c2v(plumed p);
1478 : __PLUMED_WRAPPER_C_END
1479 :
1480 :
1481 : /** \related plumed
1482 : \brief Converts a void pointer to a plumed object. Available as of PLUMED 2.5.
1483 :
1484 : It returns a plumed object from a void pointer obtained with \ref plumed_c2v.
1485 : When compiling without NDEBUG, it checks if the plumed object was properly created.
1486 :
1487 : Can be used to store a reference to a plumed object without including the Plumed.h header.
1488 : */
1489 :
1490 : __PLUMED_WRAPPER_C_BEGIN
1491 : plumed plumed_v2c(void*);
1492 : __PLUMED_WRAPPER_C_END
1493 :
1494 : #if ! defined( __cplusplus) /*{*/
1495 :
1496 : #if __PLUMED_WRAPPER_C_TYPESAFE /*{*/
1497 :
1498 : #define __PLUMED_WRAPPER_C_TYPESAFE_INNER(type_,typen_,flags_) \
1499 : static inline void plumed_cmdnse_ ## typen_(plumed p,const char*key,type_*ptr, size_t nelem, const size_t* shape,plumed_error* error) { \
1500 : plumed_safeptr safe; \
1501 : plumed_nothrow_handler nothrow; \
1502 : safe.ptr=ptr; \
1503 : safe.nelem=nelem; \
1504 : safe.shape=__PLUMED_WRAPPER_STATIC_CAST(const size_t*, shape); \
1505 : safe.flags=flags_; \
1506 : safe.opt=NULL; \
1507 : if(error) { \
1508 : plumed_error_init(error); \
1509 : nothrow.ptr=error; \
1510 : nothrow.handler=plumed_error_set; \
1511 : plumed_cmd_safe_nothrow(p,key,safe,nothrow); \
1512 : } else { \
1513 : plumed_cmd_safe(p,key,safe); \
1514 : } \
1515 : } \
1516 : static inline void plumed_cmdne_ ## typen_(plumed p,const char*key,type_*ptr, size_t nelem, plumed_error* error) { \
1517 : plumed_cmdnse_ ## typen_(p,key,ptr,nelem,NULL,error); \
1518 : } \
1519 : static inline void plumed_cmdse_ ## typen_(plumed p,const char*key,type_*ptr, const size_t* shape, plumed_error* error) { \
1520 : plumed_cmdnse_ ## typen_(p,key,ptr,0,shape,error); \
1521 : } \
1522 : static inline void plumed_cmdn_ ## typen_(plumed p,const char*key,type_*ptr, size_t nelem) { \
1523 : plumed_cmdnse_ ## typen_(p,key,ptr,nelem,NULL,NULL); \
1524 : } \
1525 : static inline void plumed_cmds_ ## typen_(plumed p,const char*key,type_*ptr, const size_t* shape) { \
1526 : plumed_cmdnse_ ## typen_(p,key,ptr,0,shape,NULL); \
1527 : } \
1528 : static inline void plumed_cmde_ ## typen_(plumed p,const char*key,type_*ptr, plumed_error* error) { \
1529 : plumed_cmdnse_ ## typen_(p,key,ptr,0,NULL,error); \
1530 : }
1531 :
1532 : #define __PLUMED_WRAPPER_C_TYPESAFE_OUTER(type,type_,code,size) \
1533 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type, type_ ## _p, size | (0x10000*(code)) | (0x2000000*2)) \
1534 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type const, type_ ## _c, size | (0x10000*(code)) | (0x2000000*3)) \
1535 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type*, type_ ## _pp, size | (0x10000*(code)) | (0x2000000*4)) \
1536 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type*const, type_ ## _pc, size | (0x10000*(code)) | (0x2000000*5)) \
1537 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type const*, type_ ## _cp, size | (0x10000*(code)) | (0x2000000*6)) \
1538 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type const*const, type_ ## _cc, size | (0x10000*(code)) | (0x2000000*7))
1539 :
1540 : #define __PLUMED_WRAPPER_C_TYPESAFE_EMPTY(type,type_,code) __PLUMED_WRAPPER_C_TYPESAFE_OUTER(type,type_,code,0)
1541 :
1542 : #define __PLUMED_WRAPPER_C_TYPESAFE_SIZED(type,type_,code) \
1543 : __PLUMED_WRAPPER_C_TYPESAFE_OUTER(type,type_,code,sizeof(type)) \
1544 : static inline void plumed_cmdnse_ ## type_ ## _v(plumed p,const char*key,type val, size_t nelem, const size_t* shape, plumed_error* error) { \
1545 : plumed_safeptr safe; \
1546 : plumed_nothrow_handler nothrow; \
1547 : (void) nelem; \
1548 : (void) shape; \
1549 : safe.ptr=&val; \
1550 : safe.nelem=1; \
1551 : safe.shape=NULL; \
1552 : safe.flags=sizeof(type) | (0x10000*(code)) | (0x2000000*1); \
1553 : safe.opt=NULL; \
1554 : if(error) { \
1555 : plumed_error_init(error); \
1556 : nothrow.ptr=error; \
1557 : nothrow.handler=plumed_error_set; \
1558 : plumed_cmd_safe_nothrow(p,key,safe,nothrow); \
1559 : } else { \
1560 : plumed_cmd_safe(p,key,safe); \
1561 : } \
1562 : } \
1563 : static inline void plumed_cmdne_ ## type_ ## _v(plumed p,const char*key,type val, size_t nelem, plumed_error* error) { \
1564 : plumed_cmdnse_ ## type_ ## _v(p,key,val,nelem,NULL,error); \
1565 : } \
1566 : static inline void plumed_cmdse_ ## type_ ## _v(plumed p,const char*key,type val, const size_t* shape, plumed_error* error) { \
1567 : plumed_cmdnse_ ## type_ ## _v(p,key,val,0,shape,error); \
1568 : } \
1569 : static inline void plumed_cmdn_ ## type_ ## _v(plumed p,const char*key,type val, size_t nelem) { \
1570 : plumed_cmdnse_ ## type_ ## _v(p,key,val,nelem,NULL,NULL); \
1571 : } \
1572 : static inline void plumed_cmds_ ## type_ ## _v(plumed p,const char*key,type val, const size_t* shape) { \
1573 : plumed_cmdnse_ ## type_ ## _v(p,key,val,0,shape,NULL); \
1574 : } \
1575 : static inline void plumed_cmde_ ## type_ ## _v(plumed p,const char*key,type val, plumed_error* error) { \
1576 : plumed_cmdnse_ ## type_ ## _v(p,key,val,0,NULL,error); \
1577 : }
1578 :
1579 : #define __PLUMED_WRAPPER_C_GENERIC1(flavor,type,typen_) \
1580 : type: plumed_ ## flavor ## _ ## typen_,
1581 :
1582 : #define __PLUMED_WRAPPER_C_GENERIC_EMPTY(flavor,type,type_) \
1583 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type*, type_ ## _p) \
1584 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type const*, type_ ## _c) \
1585 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type**, type_ ## _pp) \
1586 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type*const*, type_ ## _pc) \
1587 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type const**, type_ ## _cp) \
1588 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type const*const*, type_ ## _cc)
1589 :
1590 : #define __PLUMED_WRAPPER_C_GENERIC2(flavor,type,type_) \
1591 : __PLUMED_WRAPPER_C_GENERIC_EMPTY(flavor,type,type_) \
1592 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type, type_ ## _v)
1593 :
1594 : /// Here we create all the required instances
1595 : /// 1: void
1596 : /// 3: integral
1597 : /// 4: floating
1598 : /// 5: FILE
1599 : /// 0x100: unsigned
1600 : __PLUMED_WRAPPER_C_TYPESAFE_EMPTY(void,void,1)
1601 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(char,char,(CHAR_MIN==0)*0x100+3)
1602 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(unsigned char,unsigned_char,0x100+3)
1603 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(signed char,signed_char,0x100+3)
1604 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(short,short,3)
1605 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(unsigned short,unsigned_short,0x100+3)
1606 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(int,int,3)
1607 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(unsigned int,unsigned_int,0x100+3)
1608 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(long,long,3)
1609 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(unsigned long,unsigned_long,0x100+3)
1610 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(long long,long_long,3)
1611 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(unsigned long long,unsigned_long_long,0x100+3)
1612 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(float,float,4)
1613 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(double,double,4)
1614 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(long double,long_double,4)
1615 : __PLUMED_WRAPPER_C_TYPESAFE_EMPTY(FILE,FILE,5)
1616 :
1617 : static inline void plumed_cmd_null_e(plumed p,const char*key,plumed_error* error,int ignore) {
1618 : (void) ignore;
1619 : plumed_cmde_void_p(p,key,NULL,error);
1620 : }
1621 :
1622 : #define plumed_cmdnse_inner(flavor,val) _Generic((val), \
1623 : __PLUMED_WRAPPER_C_GENERIC_EMPTY(flavor,void,void) \
1624 : __PLUMED_WRAPPER_C_GENERIC2(flavor,char,char) \
1625 : __PLUMED_WRAPPER_C_GENERIC2(flavor,unsigned char,unsigned_char) \
1626 : __PLUMED_WRAPPER_C_GENERIC2(flavor,signed char,signed_char) \
1627 : __PLUMED_WRAPPER_C_GENERIC2(flavor,short,short) \
1628 : __PLUMED_WRAPPER_C_GENERIC2(flavor,unsigned short,unsigned_short) \
1629 : __PLUMED_WRAPPER_C_GENERIC2(flavor,int,int) \
1630 : __PLUMED_WRAPPER_C_GENERIC2(flavor,unsigned int,unsigned_int) \
1631 : __PLUMED_WRAPPER_C_GENERIC2(flavor,long,long) \
1632 : __PLUMED_WRAPPER_C_GENERIC2(flavor,unsigned long,unsigned_long) \
1633 : __PLUMED_WRAPPER_C_GENERIC2(flavor,long long,long_long) \
1634 : __PLUMED_WRAPPER_C_GENERIC2(flavor,unsigned long long,unsigned_long_long) \
1635 : __PLUMED_WRAPPER_C_GENERIC2(flavor,float,float) \
1636 : __PLUMED_WRAPPER_C_GENERIC2(flavor,double,double) \
1637 : __PLUMED_WRAPPER_C_GENERIC2(flavor,long double,long_double) \
1638 : __PLUMED_WRAPPER_C_GENERIC_EMPTY(flavor,FILE,FILE) \
1639 : default: plumed_ ## flavor ## _void_c)
1640 :
1641 : #define plumed_cmd_2args(p,key) plumed_cmdnse_inner(cmdn,NULL) (p,key,NULL,0)
1642 :
1643 : #define plumed_cmd_3args(p,key,X) _Generic((X), \
1644 : plumed_error*: plumed_cmd_null_e, \
1645 : default: plumed_cmdnse_inner(cmdn,X)) (p,key,X,0)
1646 :
1647 : /* ((X)+(size_t)0): for pointers, no op; for integers, convert to size_t */
1648 : #define plumed_cmd_4args(p,key,val,X) _Generic(((X)+(size_t)0), \
1649 : const size_t *: plumed_cmdnse_inner(cmds,val), \
1650 : size_t *: plumed_cmdnse_inner(cmds,val), \
1651 : size_t: plumed_cmdnse_inner(cmdn,val), \
1652 : plumed_error*: plumed_cmdnse_inner(cmde,val) \
1653 : ) (p,key,val,X)
1654 :
1655 : /* ((X)+(size_t)0): for pointers, no op; for integers, convert to size_t */
1656 : #define plumed_cmd_5args(p,key,val,X,error) _Generic(((X)+(size_t)0), \
1657 : const size_t *: plumed_cmdnse_inner(cmdse,val), \
1658 : size_t *: plumed_cmdnse_inner(cmdse,val), \
1659 : size_t: plumed_cmdnse_inner(cmdne,val) \
1660 : ) (p,key,val,X,error)
1661 :
1662 : #define __PLUMED_WRAPPER_C_GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
1663 : #define plumed_cmd_c11(...) __PLUMED_WRAPPER_C_GET_MACRO(__VA_ARGS__, plumed_cmd_5args, plumed_cmd_4args, plumed_cmd_3args, plumed_cmd_2args)(__VA_ARGS__)
1664 :
1665 : #define plumed_gcmd_c11(...) plumed_cmd(plumed_global(),__VA_ARGS__)
1666 :
1667 : #define __PLUMED_WRAPPER_REDEFINE_CMD plumed_cmd_c11
1668 : #define __PLUMED_WRAPPER_REDEFINE_GCMD plumed_gcmd_c11
1669 :
1670 : #endif /*}*/
1671 :
1672 : #endif /*}*/
1673 :
1674 :
1675 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
1676 :
1677 : /* Global C functions are always extern */
1678 : __PLUMED_WRAPPER_EXTERN_C_BEGIN /*{*/
1679 :
1680 : /** \relates plumed
1681 : \brief Retrieves an handler to the global structure.
1682 :
1683 : You can use this if you work on a code that uses the global structure and you want to
1684 : pass to a generic routine an handler to the same structure. E.g.
1685 :
1686 : \verbatim
1687 : plumed p=plumed_global();
1688 : some_routine(p);
1689 : \endverbatim
1690 : */
1691 : extern
1692 : plumed plumed_global(void);
1693 :
1694 : /** \relates plumed
1695 : \brief Check if the global interface has been initialized.
1696 :
1697 : \return 1 if plumed has been initialized, 0 otherwise
1698 : */
1699 : extern
1700 : int plumed_ginitialized(void);
1701 :
1702 : /** \relates plumed
1703 : \brief Constructor for the global interface.
1704 :
1705 : \note Equivalent to plumed_create(), but initialize the static global plumed object
1706 : */
1707 : extern
1708 : void plumed_gcreate(void);
1709 :
1710 : /** \relates plumed
1711 : \brief Tells to the global interface to execute a command.
1712 :
1713 : \param key The name of the command to be executed
1714 : \param val The argument. It is declared as const to allow calls like plumed_gcmd("A","B"),
1715 : but for some choice of key it can change the content
1716 :
1717 : `plumed_gcmd(a,b);` is equivalent to `plumed_cmd(plumed_global(),a,b);`.
1718 : */
1719 : extern
1720 : void plumed_gcmd(const char* key,const void* val);
1721 :
1722 : /** \relates plumed
1723 : \brief Tells to the global interface to execute a command.
1724 :
1725 : \param key The name of the command to be executed
1726 : \param safe A safe pointer
1727 :
1728 : `plumed_gcmd_safe(a,b);` is equivalent to `plumed_cmd_safe(plumed_global(),a,b);`.
1729 : */
1730 : extern
1731 : void plumed_gcmd_safe(const char* key,plumed_safeptr);
1732 :
1733 : /** \relates plumed
1734 : \brief Destructor for the global interface.
1735 :
1736 : `plumed_gfinalize(a,b);` is similar to `plumed_finalize(plumed_global(),a,b);`, but not completely
1737 : equivalent. In particular, plumed_gfinalize() also makes sure that the global object
1738 : is reset to its initial status. After calling it, \ref plumed_ginitialized() will thus return 0.
1739 : */
1740 : extern
1741 : void plumed_gfinalize(void);
1742 :
1743 : /** \relates plumed
1744 : \brief Check if global plumed object is valid. Available as of PLUMED 2.5
1745 :
1746 : It might return zero if plumed is not available at runtime.
1747 :
1748 : \return 1 if plumed is valid, 0 otherwise.
1749 : */
1750 : extern
1751 : int plumed_gvalid();
1752 :
1753 : __PLUMED_WRAPPER_EXTERN_C_END /*}*/
1754 :
1755 : #endif /*}*/
1756 :
1757 : #if defined( __cplusplus) && __PLUMED_WRAPPER_CXX /*{*/
1758 :
1759 : #if __PLUMED_WRAPPER_CXX_STD
1760 : #include <cstdlib> /* NULL getenv */
1761 : #include <cstddef> /* nullptr_t */
1762 : #include <cstring> /* strncat strlen */
1763 : #include <cassert> /* assert */
1764 : #include <climits> /* CHAR_MIN */
1765 : #else
1766 : #include <stddef.h>
1767 : #include <stdlib.h>
1768 : #include <string.h>
1769 : #include <assert.h>
1770 : #include <limits.h>
1771 : #endif
1772 :
1773 : #include <exception> /* exception bad_exception */
1774 : #include <stdexcept> /* runtime_error logic_error invalid_argument domain_error length_error out_of_range range_error overflow_error underflow_error */
1775 : #include <string> /* string */
1776 : #include <ios> /* iostream_category (C++11) ios_base::failure (C++11 and C++<11) */
1777 : #include <new> /* bad_alloc bad_array_new_length (C++11) */
1778 : #include <typeinfo> /* bad_typeid bad_cast */
1779 : #include <limits> /* numeric_limits */
1780 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
1781 : #include <system_error> /* system_error generic_category system_category */
1782 : #include <future> /* future_category */
1783 : #include <memory> /* bad_weak_ptr */
1784 : #include <functional> /* bad_function_call */
1785 : #include <regex> /* regex_error */
1786 : #endif
1787 : #if __cplusplus >= 201703L && __PLUMED_WRAPPER_LIBCXX17
1788 : #include <any> /* bad_any_cast */
1789 : #include <variant> /* bad_variant_access */
1790 : #include <optional> /* bad_optional_access */
1791 : #include <filesystem> /* filesystem_error */
1792 : #endif
1793 :
1794 : #if __cplusplus >= 201703L
1795 : #include <memory> /* unique_ptr */
1796 : #include <string_view> /* string_view */
1797 : #endif
1798 :
1799 : #if __cplusplus > 199711L
1800 : #include <array> /* array */
1801 : #include <initializer_list> /* initializer_list */
1802 : #include <type_traits> /* std::enable_if */
1803 : #endif
1804 :
1805 : /* C++ interface is hidden in PLMD namespace (same as plumed library) */
1806 : namespace PLMD {
1807 :
1808 : /* Optionally, it is further hidden in an anonymous namespace */
1809 :
1810 : __PLUMED_WRAPPER_ANONYMOUS_BEGIN /*{*/
1811 :
1812 : /**
1813 : Retrieve PLUMED_EXCEPTIONS_DEBUG (internal utility).
1814 :
1815 : This function should not be used by external programs. It is defined
1816 : as inline static so that it can store a static variable (for quicker access)
1817 : without adding a unique global symbol to a library including this header file.
1818 : */
1819 0 : inline static bool PlumedGetenvExceptionsDebug() __PLUMED_WRAPPER_CXX_NOEXCEPT {
1820 0 : static const char* res=__PLUMED_WRAPPER_STD getenv("PLUMED_EXCEPTIONS_DEBUG");
1821 0 : return res;
1822 : }
1823 :
1824 : #if __cplusplus > 199711L
1825 :
1826 : /**
1827 :
1828 : We use a separate namespace here instead of hiding these classes in the Plumed
1829 : class, because some of these structs might be specialized by the user.
1830 :
1831 : */
1832 : namespace wrapper {
1833 :
1834 : /// This is to replace c++17 std::void_t
1835 : template<typename... Ts>
1836 : struct make_void {
1837 : using type = void;
1838 : };
1839 : template<typename... Ts>
1840 : using void_t = typename make_void<Ts...>::type;
1841 :
1842 : /// Primary template, assumes T does not have both size() and data() methods
1843 : template<typename T, typename = void>
1844 : struct has_size_and_data : std::false_type {};
1845 :
1846 : /// Specialization for types T that do have both size() and data() methods
1847 : template<typename T>
1848 : struct has_size_and_data<T, void_t<decltype(std::declval<T>().size()), decltype(std::declval<T>().data())>> : std::true_type {};
1849 :
1850 : /// Primary template, assumes T is not a custom structure.
1851 : /// Can be specialized to inform about custom structures
1852 : template<typename T>
1853 : struct is_custom_array : std::false_type {
1854 : typedef void value_type;
1855 : };
1856 :
1857 : /// Template specialization for std::array
1858 : template<typename T, std::size_t N>
1859 : struct is_custom_array<std::array<T,N>> : std::true_type {
1860 : using value_type = typename std::array<T,N>::value_type;
1861 : };
1862 :
1863 : /// Template specialization for C arrays.
1864 : /// Note: we have to use it as wrapper::is_custom_array<typename std::remove_reference<T>::type>::value
1865 : /// because C arrays are only passed by reference!
1866 : template<typename T, std::size_t N>
1867 : struct is_custom_array<T[N]> : std::true_type {
1868 : using value_type = typename std::remove_reference<decltype(std::declval<T[N]>()[0])>::type;
1869 : };
1870 :
1871 : /// Generic utility to retrieve the size of a container
1872 : template<typename T>
1873 : inline std::size_t size(const T&obj) {
1874 : return obj.size();
1875 : }
1876 :
1877 : /// Specialization for std::string, which returns size()+1, which includes the terminating null character
1878 : template<>
1879 : inline std::size_t size(const std::string &obj) {
1880 : return obj.size()+1;
1881 : }
1882 :
1883 : /// Report the size of a custom_array.
1884 : /// typename std::remove_reference<T>::type is needed because C arrays are passed by reference
1885 : template<typename T, typename std::enable_if<wrapper::is_custom_array<typename std::remove_reference<T>::type>::value, int>::type = 0>
1886 : inline std::size_t custom_array_size() {
1887 : using value_type = typename wrapper::is_custom_array<typename std::remove_reference<T>::type>::value_type;
1888 : constexpr std::size_t value_size=sizeof(value_type);
1889 : static_assert(value_size>0,"cannot use custom arrays of void types");
1890 : static_assert(sizeof(T)%value_size==0,"custom array has incorrect size");
1891 : return sizeof(T)/sizeof(value_type);
1892 : }
1893 :
1894 : /// Cast a pointer to a custom_array to a pointer of its value_type.
1895 : /// typename std::remove_reference<T>::type is needed because C arrays are passed by reference
1896 : template<typename T, typename std::enable_if<wrapper::is_custom_array<typename std::remove_reference<T>::type>::value, int>::type = 0>
1897 : inline typename wrapper::is_custom_array<T>::value_type* custom_array_cast(T* val) {
1898 : using value_type = typename wrapper::is_custom_array<typename std::remove_reference<T>::type>::value_type;
1899 : return reinterpret_cast<value_type*>(val);
1900 : }
1901 :
1902 : }
1903 :
1904 : #endif
1905 :
1906 :
1907 : /**
1908 : C++ wrapper for \ref plumed.
1909 :
1910 : This class provides a C++ interface to PLUMED.
1911 : It only containts a \ref plumed object, but wraps it with a number of useful methods.
1912 : All methods are inlined so as to avoid the compilation of an extra c++ file.
1913 :
1914 : */
1915 :
1916 : class Plumed {
1917 : /**
1918 : C structure.
1919 : */
1920 : plumed main;
1921 :
1922 : private:
1923 :
1924 : /**
1925 : This is an internal utility to dispatch exceptions based on the plumed_error object.
1926 :
1927 : It takes information about the exception to be thrown by the passed h object
1928 : and use it to call function f() on the resulting exception. Notice that:
1929 : - this function does not consider if the error is nested.
1930 : - f should be a callable object, so that it can store information
1931 : - f operator() should be a template function so as to act based on the
1932 : type of its argument
1933 :
1934 : New exceptions added here should be kept in sync with core/PlumedMainInitializer.cpp
1935 :
1936 : Notice that this function also finalizes in place plumed_error h, so as to avoid
1937 : memory leaks.
1938 : */
1939 : template<typename F>
1940 0 : __PLUMED_WRAPPER_CXX_NORETURN static void exception_dispatch(plumed_error&h,F f) {
1941 : /* this is required to make sure h is finalized when leaving this function */
1942 : finalize_plumed_error finalize(h);
1943 : /* grab the message */
1944 : const char* msg=plumed_error_what(h);
1945 0 : if(h.code==1) {
1946 0 : f(Plumed::Invalid(msg));
1947 : }
1948 : /* logic errors */
1949 0 : if(h.code>=10100 && h.code<10200) {
1950 0 : if(h.code>=10105 && h.code<10110) {
1951 0 : f(::std::invalid_argument(msg));
1952 : }
1953 0 : if(h.code>=10110 && h.code<10115) {
1954 0 : f(::std::domain_error(msg));
1955 : }
1956 0 : if(h.code>=10115 && h.code<10120) {
1957 0 : f(::std::length_error(msg));
1958 : }
1959 0 : if(h.code>=10120 && h.code<10125) {
1960 0 : f(::std::out_of_range(msg));
1961 : }
1962 : #if __cplusplus >= 201703L && __PLUMED_WRAPPER_LIBCXX17
1963 : if(h.code==10125) {
1964 : f(add_buffer_to< ::std::future_error>(::std::future_error(::std::future_errc::broken_promise),msg));
1965 : }
1966 : if(h.code==10126) {
1967 : f(add_buffer_to< ::std::future_error>(::std::future_error(::std::future_errc::future_already_retrieved),msg));
1968 : }
1969 : if(h.code==10127) {
1970 : f(add_buffer_to< ::std::future_error>(::std::future_error(::std::future_errc::promise_already_satisfied),msg));
1971 : }
1972 : if(h.code==10128) {
1973 : f(add_buffer_to< ::std::future_error>(::std::future_error(::std::future_errc::no_state),msg));
1974 : }
1975 : #endif
1976 0 : f(::std::logic_error(msg));
1977 : }
1978 : /* runtime errors */
1979 0 : if(h.code>=10200 && h.code<10300) {
1980 0 : if(h.code>=10205 && h.code<10210) {
1981 0 : f(::std::range_error(msg));
1982 : }
1983 : if(h.code>=10210 && h.code<10215) {
1984 0 : f(::std::overflow_error(msg));
1985 : }
1986 : if(h.code>=10215 && h.code<10220) {
1987 0 : f(::std::underflow_error(msg));
1988 : }
1989 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
1990 : if(h.code==10220) {
1991 0 : f(::std::system_error(h.error_code,::std::generic_category(),msg));
1992 : }
1993 : if(h.code==10221) {
1994 0 : f(::std::system_error(h.error_code,::std::system_category(),msg));
1995 : }
1996 : if(h.code==10222) {
1997 0 : f(::std::system_error(h.error_code,::std::iostream_category(),msg));
1998 : }
1999 : if(h.code==10223) {
2000 0 : f(::std::system_error(h.error_code,::std::future_category(),msg));
2001 : }
2002 : #endif
2003 : #if __cplusplus >= 201703L && __PLUMED_WRAPPER_LIBCXX17
2004 : if(h.code==10229) {
2005 : ::std::error_code error_code;
2006 : if(h.error_category==1) {
2007 : error_code=::std::error_code(h.error_code,::std::generic_category());
2008 : }
2009 : if(h.error_category==2) {
2010 : error_code=::std::error_code(h.error_code,::std::system_category());
2011 : }
2012 : if(h.error_category==3) {
2013 : error_code=::std::error_code(h.error_code,::std::iostream_category());
2014 : }
2015 : if(h.error_category==4) {
2016 : error_code=::std::error_code(h.error_code,::std::future_category());
2017 : }
2018 :
2019 : if(!h.path1.ptr) {
2020 : f(::std::filesystem::filesystem_error(msg,error_code));
2021 : } else if(!h.path2.ptr) {
2022 : /*
2023 : In principle native_format is a possible value of an enum,
2024 : so should be accessible as ::std::filesystem::path::native_format
2025 : However, some clang versions declare it as enum class. Thus,
2026 : ::std::filesystem::path::format::native_format is more portable.
2027 : */
2028 : f(::std::filesystem::filesystem_error(msg,
2029 : ::std::filesystem::path(::std::filesystem::path::string_type(
2030 : reinterpret_cast<::std::filesystem::path::value_type*>(h.path1.ptr),
2031 : h.path1.numbytes/sizeof(::std::filesystem::path::value_type)
2032 : ),
2033 : ::std::filesystem::path::format::native_format),
2034 : error_code));
2035 : } else {
2036 : f(::std::filesystem::filesystem_error(msg,
2037 : ::std::filesystem::path(::std::filesystem::path::string_type(
2038 : reinterpret_cast<::std::filesystem::path::value_type*>(h.path1.ptr),
2039 : h.path1.numbytes/sizeof(::std::filesystem::path::value_type)
2040 : ),
2041 : ::std::filesystem::path::format::native_format),
2042 : ::std::filesystem::path(::std::filesystem::path::string_type(
2043 : reinterpret_cast<::std::filesystem::path::value_type*>(h.path2.ptr),
2044 : h.path2.numbytes/sizeof(::std::filesystem::path::value_type)
2045 : ),
2046 : ::std::filesystem::path::format::native_format),
2047 : error_code));
2048 : }
2049 : }
2050 : #endif
2051 : if(h.code>=10230 && h.code<10240) {
2052 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2053 : // These cases are probably useless as it looks like this should always be std::iostream_category
2054 0 : if(h.code==10230) {
2055 0 : f(::std::ios_base::failure(msg,::std::error_code(h.error_code,::std::generic_category())));
2056 : }
2057 0 : if(h.code==10231) {
2058 0 : f(::std::ios_base::failure(msg,::std::error_code(h.error_code,::std::system_category())));
2059 : }
2060 0 : if(h.code==10232) {
2061 0 : f(::std::ios_base::failure(msg,::std::error_code(h.error_code,::std::iostream_category())));
2062 : }
2063 0 : if(h.code==10233) {
2064 0 : f(::std::ios_base::failure(msg,::std::error_code(h.error_code,::std::future_category())));
2065 : }
2066 : #endif
2067 0 : f(::std::ios_base::failure(msg));
2068 : }
2069 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2070 : if(h.code==10240) {
2071 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_collate),msg));
2072 : }
2073 : if(h.code==10241) {
2074 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_ctype),msg));
2075 : }
2076 : if(h.code==10242) {
2077 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_escape),msg));
2078 : }
2079 : if(h.code==10243) {
2080 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_backref),msg));
2081 : }
2082 : if(h.code==10244) {
2083 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_brack),msg));
2084 : }
2085 : if(h.code==10245) {
2086 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_paren),msg));
2087 : }
2088 : if(h.code==10246) {
2089 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_brace),msg));
2090 : }
2091 : if(h.code==10247) {
2092 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_badbrace),msg));
2093 : }
2094 : if(h.code==10248) {
2095 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_range),msg));
2096 : }
2097 : if(h.code==10249) {
2098 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_space),msg));
2099 : }
2100 : if(h.code==10250) {
2101 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_badrepeat),msg));
2102 : }
2103 : if(h.code==10251) {
2104 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_complexity),msg));
2105 : }
2106 : if(h.code==10252) {
2107 0 : f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_stack),msg));
2108 : }
2109 : #endif
2110 0 : f(::std::runtime_error(msg));
2111 : }
2112 : /* "bad" errors */
2113 : /* "< ::" space required in C++ < 11 */
2114 0 : if(h.code>=11000 && h.code<11100) {
2115 0 : f(add_buffer_to< ::std::bad_typeid>(msg));
2116 : }
2117 0 : if(h.code>=11100 && h.code<11200) {
2118 : #if __cplusplus >= 201703L && __PLUMED_WRAPPER_LIBCXX17
2119 : if(h.code>=11150) {
2120 : f(add_buffer_to< ::std::bad_any_cast>(msg));
2121 : }
2122 : #endif
2123 0 : f(add_buffer_to< ::std::bad_cast>(msg));
2124 : }
2125 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2126 0 : if(h.code>=11200 && h.code<11300) {
2127 0 : f(add_buffer_to< ::std::bad_weak_ptr>(msg));
2128 : }
2129 0 : if(h.code>=11300 && h.code<11400) {
2130 0 : f(add_buffer_to< ::std::bad_function_call>(msg));
2131 : }
2132 : #endif
2133 0 : if(h.code>=11400 && h.code<11500) {
2134 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2135 0 : if(h.code>=11410 && h.code<11420) {
2136 0 : f(add_buffer_to< ::std::bad_array_new_length>(msg));
2137 : }
2138 : #endif
2139 0 : f(add_buffer_to< ::std::bad_alloc>(msg));
2140 : }
2141 0 : if(h.code>=11500 && h.code<11600) {
2142 0 : f(add_buffer_to< ::std::bad_exception>(msg));
2143 : }
2144 : #if __cplusplus >= 201703L && __PLUMED_WRAPPER_LIBCXX17
2145 : if(h.code>=11600 && h.code<11700) {
2146 : f(add_buffer_to< ::std::bad_optional_access>(msg));
2147 : }
2148 : if(h.code>=11700 && h.code<11800) {
2149 : f(add_buffer_to< ::std::bad_variant_access>(msg));
2150 : }
2151 : #endif
2152 : /* lepton error */
2153 0 : if(h.code>=19900 && h.code<20000) {
2154 0 : f(Plumed::LeptonException(msg));
2155 : }
2156 : /* plumed exceptions */
2157 0 : if(h.code>=20000 && h.code<30000) {
2158 : /* debug - only raised with debug options */
2159 0 : if(h.code>=20100 && h.code<20200) {
2160 0 : f(Plumed::ExceptionDebug(msg));
2161 : }
2162 : /* error - runtime check */
2163 0 : if(h.code>=20200 && h.code<20300) {
2164 0 : f(Plumed::ExceptionError(msg));
2165 : }
2166 : /* error - type error */
2167 0 : if(h.code>=20300 && h.code<20400) {
2168 0 : f(Plumed::ExceptionTypeError(msg));
2169 : }
2170 0 : f(Plumed::Exception(msg));
2171 : }
2172 : /* fallback for any other exception */
2173 0 : f(add_buffer_to< ::std::exception>(msg));
2174 0 : }
2175 :
2176 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_CXX_ENABLE_NESTED_EXCEPTIONS
2177 : /** Internal class used by exception_dispatch. */
2178 : class rethrow_nested {
2179 : public:
2180 : template<typename E>
2181 : __PLUMED_WRAPPER_CXX_NORETURN void operator()(const E&e) {
2182 0 : std::throw_with_nested(e);
2183 : }
2184 : };
2185 : #endif
2186 :
2187 : /** Internal class used by exception_dispatch. */
2188 : class rethrow_not_nested {
2189 : public:
2190 : template<typename E>
2191 0 : __PLUMED_WRAPPER_CXX_NORETURN void operator()(const E&e) {
2192 0 : throw e;
2193 : }
2194 : };
2195 :
2196 : /** Internal class to simplify plumed_error finalization */
2197 : class finalize_plumed_error {
2198 : plumed_error&e;
2199 : finalize_plumed_error(const finalize_plumed_error&); //not implemented
2200 : public:
2201 0 : __PLUMED_WRAPPER_CXX_EXPLICIT finalize_plumed_error(plumed_error&e):
2202 0 : e(e)
2203 : {}
2204 0 : ~finalize_plumed_error() {
2205 0 : plumed_error_finalize(e);
2206 0 : e.code=0; // make sure it's not finalized again
2207 0 : }
2208 : };
2209 :
2210 : /**
2211 : Recursive function that rethrows an exception with all the nested ones.
2212 :
2213 : In order to do so, we start throwing from the first exception that was originally thrown
2214 : and recursively throw the others using throw_with_nested.
2215 :
2216 : plumed_error h is finalized at exit by the exception_dispatch function, to avoid memory leaks
2217 : */
2218 0 : __PLUMED_WRAPPER_CXX_NORETURN static void rethrow(plumed_error&h) {
2219 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_CXX_ENABLE_NESTED_EXCEPTIONS
2220 : /*
2221 : When using C++11 nested exceptions, we need to rethrow recursively
2222 : */
2223 : try {
2224 0 : if(h.nested) {
2225 0 : rethrow(*h.nested); /* recursive throw */
2226 : }
2227 0 : } catch(...) {
2228 0 : exception_dispatch(h,rethrow_nested());
2229 0 : }
2230 0 : exception_dispatch(h,rethrow_not_nested());
2231 : #else
2232 : /*
2233 : When using C++<11 exceptions, we merge the message and then throw the resulting exception
2234 : */
2235 : if(h.nested) {
2236 : plumed_error_merge_with_nested(&h);
2237 : }
2238 : exception_dispatch(h,rethrow_not_nested());
2239 : #endif
2240 : }
2241 :
2242 : public:
2243 : /**
2244 : This is a tool to rethrow an error as an exception and finalize the error.
2245 :
2246 : In practice, this makes it possible to write a code like this:
2247 : ```
2248 : Plumed p;
2249 : plumed_error e;
2250 : // store error in e if something wrong happes
2251 : // notice that Plumed (C++) is implicitly converted to plumed (C) when calling plumed_cmd
2252 : plumed_cmd(p,"init",&e);
2253 : // do other things here
2254 : // then throw the exception
2255 : if(e.code) plumed_error_rethrow(e);
2256 :
2257 : It should be used through the macro plumed_error_rethrow.
2258 : ```
2259 : */
2260 : __PLUMED_WRAPPER_CXX_NORETURN static void plumed_error_rethrow_cxx(plumed_error h) {
2261 0 : rethrow(h);
2262 : }
2263 :
2264 : private:
2265 : /**
2266 : Rethrow the current exception.
2267 :
2268 : This is useful in order to handle an exception thrown by a kernel <=2.4.
2269 : Only std exceptions are handled, though some of them are thrown as special
2270 : Plumed exceptions in order to be attached a message.
2271 : */
2272 0 : __PLUMED_WRAPPER_CXX_NORETURN static void rethrow() {
2273 : try {
2274 0 : throw;
2275 0 : } catch(const ::std::bad_exception & e) {
2276 0 : throw add_buffer_to< ::std::bad_exception>(e.what());
2277 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2278 0 : } catch(const ::std::bad_array_new_length & e) {
2279 0 : throw add_buffer_to< ::std::bad_array_new_length>(e.what());
2280 : #endif
2281 0 : } catch(const ::std::bad_alloc & e) {
2282 0 : throw add_buffer_to< ::std::bad_alloc>(e.what());
2283 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2284 0 : } catch(const ::std::bad_function_call & e) {
2285 0 : throw add_buffer_to< ::std::bad_function_call>(e.what());
2286 0 : } catch(const ::std::bad_weak_ptr & e) {
2287 0 : throw add_buffer_to< ::std::bad_weak_ptr>(e.what());
2288 : #endif
2289 0 : } catch(const ::std::bad_cast & e) {
2290 0 : throw add_buffer_to< ::std::bad_cast>(e.what());
2291 0 : } catch(const ::std::bad_typeid & e) {
2292 0 : throw add_buffer_to< ::std::bad_typeid>(e.what());
2293 : // not implemented yet: std::regex_error
2294 : // we do not allow regex yet due to portability problems with gcc 4.8
2295 : // as soon as we transition to using <regex> it should be straightforward to add
2296 0 : } catch(const ::std::ios_base::failure & e) {
2297 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2298 0 : throw ::std::ios_base::failure(e.what(),e.code());
2299 : #else
2300 : throw ::std::ios_base::failure(e.what());
2301 : #endif
2302 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2303 0 : } catch(const ::std::system_error & e) {
2304 0 : throw ::std::system_error(e.code(),e.what());
2305 : #endif
2306 0 : } catch(const ::std::underflow_error &e) {
2307 0 : throw ::std::underflow_error(e.what());
2308 0 : } catch(const ::std::overflow_error &e) {
2309 0 : throw ::std::overflow_error(e.what());
2310 0 : } catch(const ::std::range_error &e) {
2311 0 : throw ::std::range_error(e.what());
2312 0 : } catch(const ::std::runtime_error & e) {
2313 0 : throw ::std::runtime_error(e.what());
2314 : // not implemented yet: std::future_error
2315 : // not clear how useful it would be.
2316 0 : } catch(const ::std::out_of_range & e) {
2317 0 : throw ::std::out_of_range(e.what());
2318 0 : } catch(const ::std::length_error & e) {
2319 0 : throw ::std::length_error(e.what());
2320 0 : } catch(const ::std::domain_error & e) {
2321 0 : throw ::std::domain_error(e.what());
2322 0 : } catch(const ::std::invalid_argument & e) {
2323 0 : throw ::std::invalid_argument(e.what());
2324 0 : } catch(const ::std::logic_error & e) {
2325 0 : throw ::std::logic_error(e.what());
2326 0 : } catch(const ::std::exception & e) {
2327 0 : throw add_buffer_to< ::std::exception>(e.what());
2328 0 : } catch(...) {
2329 0 : throw add_buffer_to< ::std::bad_exception>("plumed could not translate exception");
2330 0 : }
2331 : }
2332 :
2333 : public:
2334 :
2335 : #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS
2336 : using Exception = PLMD::Exception;
2337 : #else
2338 : /**
2339 : Base class used to rethrow PLUMED exceptions.
2340 : */
2341 : class Exception :
2342 : public ::std::exception {
2343 : ::std::string msg;
2344 : public:
2345 0 : __PLUMED_WRAPPER_CXX_EXPLICIT Exception(const char* msg): msg(msg) {}
2346 0 : const char* what() const __PLUMED_WRAPPER_CXX_NOEXCEPT __PLUMED_WRAPPER_CXX_OVERRIDE {
2347 0 : return msg.c_str();
2348 : }
2349 : #if ! (__cplusplus > 199711L)
2350 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2351 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2352 : ~Exception() throw() {}
2353 : #endif
2354 : };
2355 : #endif
2356 :
2357 : #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS
2358 : using ExceptionError = PLMD::ExceptionError;
2359 : #else
2360 : /**
2361 : Used to rethrow a PLMD::ExceptionError
2362 : */
2363 0 : class ExceptionError :
2364 : public Exception {
2365 : public:
2366 0 : __PLUMED_WRAPPER_CXX_EXPLICIT ExceptionError(const char* msg): Exception(msg) {}
2367 : #if ! (__cplusplus > 199711L)
2368 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2369 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2370 : ~ExceptionError() throw() {}
2371 : #endif
2372 : };
2373 : #endif
2374 :
2375 : #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS
2376 : using ExceptionDebug = PLMD::ExceptionDebug;
2377 : #else
2378 : /**
2379 : Used to rethrow a PLMD::ExceptionDebug
2380 : */
2381 0 : class ExceptionDebug :
2382 : public Exception {
2383 : public:
2384 0 : __PLUMED_WRAPPER_CXX_EXPLICIT ExceptionDebug(const char* msg): Exception(msg) {}
2385 : #if ! (__cplusplus > 199711L)
2386 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2387 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2388 : ~ExceptionDebug() throw() {}
2389 : #endif
2390 : };
2391 : #endif
2392 :
2393 : /**
2394 : Thrown when trying to access an invalid plumed object
2395 : */
2396 :
2397 0 : class Invalid :
2398 : public Exception {
2399 : public:
2400 0 : __PLUMED_WRAPPER_CXX_EXPLICIT Invalid(const char* msg): Exception(msg) {}
2401 : #if ! (__cplusplus > 199711L)
2402 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2403 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2404 : ~Invalid() throw() {}
2405 : #endif
2406 : };
2407 :
2408 : #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS
2409 : using ExceptionTypeError = PLMD::ExceptionTypeError;
2410 : #else
2411 : /**
2412 : Thrown when a wrong pointer is passed to the PLUMED interface.
2413 : */
2414 0 : class ExceptionTypeError:
2415 : public Exception {
2416 : public:
2417 0 : __PLUMED_WRAPPER_CXX_EXPLICIT ExceptionTypeError(const char* msg): Exception(msg) {}
2418 : #if ! (__cplusplus > 199711L)
2419 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2420 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2421 : ~ExceptionTypeError() throw() {}
2422 : #endif
2423 : };
2424 : #endif
2425 :
2426 : #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS
2427 : using LeptonException = PLMD::lepton::Exception;
2428 : #else
2429 : /**
2430 : Class used to rethrow Lepton exceptions.
2431 : */
2432 :
2433 : class LeptonException :
2434 : public ::std::exception {
2435 : ::std::string msg;
2436 : public:
2437 0 : __PLUMED_WRAPPER_CXX_EXPLICIT LeptonException(const char* msg): msg(msg) {}
2438 0 : const char* what() const __PLUMED_WRAPPER_CXX_NOEXCEPT __PLUMED_WRAPPER_CXX_OVERRIDE {
2439 0 : return msg.c_str();
2440 : }
2441 : #if ! (__cplusplus > 199711L)
2442 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2443 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2444 : ~LeptonException() throw() {}
2445 : #endif
2446 : };
2447 : #endif
2448 :
2449 : private:
2450 : /*
2451 : These exceptions are declared as private as they are not supposed to be
2452 : catched by value. they only exist to allow a buffer to be attached to
2453 : the std::exceptions that do not contain it already.
2454 : Notice that these exceptions are those whose constructor should never throw, and as
2455 : such they use a fixed size buffer.
2456 : */
2457 :
2458 : template<typename T>
2459 0 : class add_buffer_to:
2460 : public T {
2461 : char msg[__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER];
2462 0 : void init(const char* msg) __PLUMED_WRAPPER_CXX_NOEXCEPT {
2463 0 : this->msg[0]='\0';
2464 0 : __PLUMED_WRAPPER_STD strncpy(this->msg,msg,__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER-1);
2465 0 : this->msg[__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER-1]='\0';
2466 0 : if(PlumedGetenvExceptionsDebug() && __PLUMED_WRAPPER_STD strlen(msg) > __PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER-1) {
2467 0 : __PLUMED_WRAPPER_STD fprintf(stderr,"+++ WARNING: message will be truncated\n");
2468 : }
2469 0 : }
2470 : public:
2471 0 : __PLUMED_WRAPPER_CXX_EXPLICIT add_buffer_to(const char * msg) __PLUMED_WRAPPER_CXX_NOEXCEPT {
2472 0 : init(msg);
2473 : }
2474 0 : add_buffer_to(const T& base,const char * msg) __PLUMED_WRAPPER_CXX_NOEXCEPT:
2475 0 : T(base) {
2476 0 : init(msg);
2477 0 : }
2478 0 : add_buffer_to(const add_buffer_to & other) __PLUMED_WRAPPER_CXX_NOEXCEPT:
2479 0 : T(other) {
2480 0 : init(other.msg);
2481 0 : }
2482 : add_buffer_to & operator=(const add_buffer_to & other) __PLUMED_WRAPPER_CXX_NOEXCEPT {
2483 : if(this==&other) {
2484 : return *this;
2485 : }
2486 : init(other.msg);
2487 : return *this;
2488 : }
2489 0 : const char* what() const __PLUMED_WRAPPER_CXX_NOEXCEPT __PLUMED_WRAPPER_CXX_OVERRIDE {
2490 0 : return msg;
2491 : }
2492 : #if ! (__cplusplus > 199711L)
2493 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2494 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2495 : ~add_buffer_to() throw() {}
2496 : #endif
2497 : };
2498 :
2499 : private:
2500 : /// Small class that wraps plumed_safeptr in order to make its initialization easier
2501 : class SafePtr {
2502 : /// non copyable (copy would require managing buffer, could be added in the future if needed)
2503 : SafePtr(const SafePtr&);
2504 : /// non assignable (assignment would require managing buffer, could be added in the future if needed)
2505 : SafePtr& operator=(SafePtr const&);
2506 : public:
2507 : plumed_safeptr safe;
2508 : /// This buffer holds a copy of the data when they are passed by value.
2509 : /// The size is sufficient to hold any primitive type.
2510 : /// Notice that the buffer is required to enable conversions (e.g., passing a class that can be converted to int)
2511 : /// and, at the same time, allow the object to exist after SafePtr constructor has completed.
2512 : /// A perhaps cleaner implementation would require a base class containing
2513 : /// the plumed_safeptr object, derived classes depending on the
2514 : /// argument type as a template parameter, and overloaded functions
2515 : /// returning this derived class.
2516 : char buffer[32];
2517 : /// Default constructor, nullptr
2518 : SafePtr() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2519 : safe.ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
2520 : safe.nelem=0;
2521 : safe.shape=__PLUMED_WRAPPER_CXX_NULLPTR;
2522 : safe.flags=0x10000*2;
2523 : safe.opt=__PLUMED_WRAPPER_CXX_NULLPTR;
2524 : buffer[0]='\0';
2525 : }
2526 :
2527 222 : __PLUMED_WRAPPER_CXX_EXPLICIT SafePtr(const plumed_safeptr & safe,__PLUMED_WRAPPER_STD size_t nelem=0, const __PLUMED_WRAPPER_STD size_t* shape=__PLUMED_WRAPPER_CXX_NULLPTR) __PLUMED_WRAPPER_CXX_NOEXCEPT {
2528 222 : this->safe=safe;
2529 222 : buffer[0]='\0';
2530 : if(nelem>0) {
2531 : this->safe.nelem=nelem;
2532 : }
2533 : if(shape) {
2534 : this->safe.shape=const_cast<__PLUMED_WRAPPER_STD size_t*>(shape);
2535 : }
2536 : }
2537 :
2538 : #if __cplusplus > 199711L
2539 : /// Construct from null
2540 : SafePtr(__PLUMED_WRAPPER_STD nullptr_t,__PLUMED_WRAPPER_STD size_t nelem, const __PLUMED_WRAPPER_STD size_t* shape) noexcept {
2541 : safe.ptr=nullptr;
2542 : safe.nelem=0;
2543 : safe.shape=nullptr;
2544 : safe.flags=0x10000*2;
2545 : safe.opt=nullptr;
2546 : buffer[0]='\0';
2547 : (void) nelem;
2548 : (void) shape;
2549 : }
2550 : #endif
2551 :
2552 : /// Macro that generate a constructor with given type and flags
2553 : #define __PLUMED_WRAPPER_SAFEPTR_INNER(type_,flags_) \
2554 : SafePtr(type_*ptr, __PLUMED_WRAPPER_STD size_t nelem, const __PLUMED_WRAPPER_STD size_t* shape) __PLUMED_WRAPPER_CXX_NOEXCEPT { \
2555 : safe.ptr=ptr; \
2556 : safe.nelem=nelem; \
2557 : safe.shape=const_cast<__PLUMED_WRAPPER_STD size_t*>(shape); \
2558 : safe.flags=flags_; \
2559 : safe.opt=__PLUMED_WRAPPER_CXX_NULLPTR; \
2560 : buffer[0]='\0'; \
2561 : }
2562 :
2563 : /// Macro that uses __PLUMED_WRAPPER_SAFEPTR_INNER to generate constructors with
2564 : /// all possible pointer-const combinations
2565 : #define __PLUMED_WRAPPER_SAFEPTR(type,code,size) \
2566 : __PLUMED_WRAPPER_SAFEPTR_INNER(type, size | (0x10000*(code)) | (0x2000000*2)) \
2567 : __PLUMED_WRAPPER_SAFEPTR_INNER(type const, size | (0x10000*(code)) | (0x2000000*3)) \
2568 : __PLUMED_WRAPPER_SAFEPTR_INNER(type*, size | (0x10000*(code)) | (0x2000000*4)) \
2569 : __PLUMED_WRAPPER_SAFEPTR_INNER(type*const, size | (0x10000*(code)) | (0x2000000*5)) \
2570 : __PLUMED_WRAPPER_SAFEPTR_INNER(type const*, size | (0x10000*(code)) | (0x2000000*6)) \
2571 : __PLUMED_WRAPPER_SAFEPTR_INNER(type const*const, size | (0x10000*(code)) | (0x2000000*7))
2572 :
2573 : /// Macro that generates the constructors from empy types (those of which sizeof cannot be computed)
2574 : #define __PLUMED_WRAPPER_SAFEPTR_EMPTY(type,code) __PLUMED_WRAPPER_SAFEPTR(type,code,0)
2575 :
2576 : /// Macro that generates the constructors from sized types (those of which sizeof can be computed).
2577 : /// In addition to generating constructors with all pointer types, it generates a constructor to
2578 : /// allow pass-by-value
2579 : #define __PLUMED_WRAPPER_SAFEPTR_SIZED(type,code) \
2580 : __PLUMED_WRAPPER_SAFEPTR(type,code,sizeof(type)) \
2581 : SafePtr(type val, __PLUMED_WRAPPER_STD size_t nelem, const __PLUMED_WRAPPER_STD size_t* shape) __PLUMED_WRAPPER_CXX_NOEXCEPT { \
2582 : assert(sizeof(type)<=32); \
2583 : (void) nelem; \
2584 : (void) shape; \
2585 : safe.ptr=buffer; \
2586 : safe.nelem=1; \
2587 : safe.shape=__PLUMED_WRAPPER_CXX_NULLPTR; \
2588 : safe.flags=sizeof(type) | (0x10000*(code)) | (0x2000000*1); \
2589 : safe.opt=__PLUMED_WRAPPER_CXX_NULLPTR; \
2590 : __PLUMED_WRAPPER_STD memcpy(buffer,&val,sizeof(type)); \
2591 : }
2592 :
2593 : /// Here we create all the required instances
2594 : /// 1: void
2595 : /// 3: integral
2596 : /// 4: floating
2597 : /// 5: FILE
2598 : /// 0x100: unsigned
2599 361 : __PLUMED_WRAPPER_SAFEPTR_EMPTY(void,1)
2600 5364 : __PLUMED_WRAPPER_SAFEPTR_SIZED(char,(CHAR_MIN==0)*0x100+3)
2601 : __PLUMED_WRAPPER_SAFEPTR_SIZED(unsigned char,3)
2602 : __PLUMED_WRAPPER_SAFEPTR_SIZED(signed char,0x100+3)
2603 : __PLUMED_WRAPPER_SAFEPTR_SIZED(short,3)
2604 : __PLUMED_WRAPPER_SAFEPTR_SIZED(unsigned short,0x100+3)
2605 10728 : __PLUMED_WRAPPER_SAFEPTR_SIZED(int,3)
2606 : __PLUMED_WRAPPER_SAFEPTR_SIZED(unsigned int,0x100+3)
2607 : __PLUMED_WRAPPER_SAFEPTR_SIZED(long,3)
2608 : __PLUMED_WRAPPER_SAFEPTR_SIZED(unsigned long,0x100+3)
2609 : #if __PLUMED_WRAPPER_CXX_LONGLONG
2610 : __PLUMED_WRAPPER_SAFEPTR_SIZED(long long,3)
2611 : __PLUMED_WRAPPER_SAFEPTR_SIZED(unsigned long long,0x100+3)
2612 : #endif
2613 : __PLUMED_WRAPPER_SAFEPTR_SIZED(float,4)
2614 : __PLUMED_WRAPPER_SAFEPTR_SIZED(double,4)
2615 : __PLUMED_WRAPPER_SAFEPTR_SIZED(long double,4)
2616 : __PLUMED_WRAPPER_SAFEPTR_EMPTY(FILE,5)
2617 :
2618 : /// Return the contained plumed_safeptr
2619 : plumed_safeptr get_safeptr() const __PLUMED_WRAPPER_CXX_NOEXCEPT {
2620 16675 : return safe;
2621 : }
2622 :
2623 : };
2624 :
2625 : #if __cplusplus > 199711L
2626 : /// Small structure used to pass elements of a shape initializer_list.
2627 : /// We use simple conversions, without sign checks, which implicitly means that size=-1 is a very large size
2628 : struct SizeLike {
2629 : std::size_t size;
2630 : SizeLike(short unsigned size): size(size) {}
2631 : SizeLike(unsigned size): size(size) {}
2632 : SizeLike(long unsigned size): size(size) {}
2633 : SizeLike(long long unsigned size): size(size) {}
2634 : SizeLike(short size): size(std::size_t(size)) {}
2635 5364 : SizeLike(int size): size(std::size_t(size)) {}
2636 : SizeLike(long int size): size(std::size_t(size)) {}
2637 : SizeLike(long long int size): size(std::size_t(size)) {}
2638 : };
2639 : #endif
2640 :
2641 : public:
2642 :
2643 : /**
2644 : Check if plumed is installed (for runtime binding)
2645 : \return true if plumed is installed, false otherwise
2646 : \note Equivalent to plumed_installed() but returns a bool
2647 : */
2648 : static bool installed() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2649 : return plumed_installed();
2650 : }
2651 : /**
2652 : Check if Plumed object is valid. Available as of PLUMED 2.5
2653 : \return true if plumed is valid, false otherwise
2654 : \note Equivalent to plumed_valid() but returns a bool
2655 : */
2656 : bool valid() const __PLUMED_WRAPPER_CXX_NOEXCEPT {
2657 : return plumed_valid(main);
2658 : }
2659 : #if __cplusplus > 199711L
2660 : /**
2661 : Same as \ref valid(). Available as of PLUMED 2.5.
2662 :
2663 : Allow code such as
2664 : \verbatim
2665 : Plumed p;
2666 : if(!p) raise_error();
2667 : p.cmd("init");
2668 : \endverbatim
2669 :
2670 : In order to avoid ambiguous conversions, this is only allowed when compiling with C++11
2671 : where it is marked as explicit.
2672 : */
2673 : explicit
2674 : operator bool() const __PLUMED_WRAPPER_CXX_NOEXCEPT {
2675 : return plumed_valid(main);
2676 : }
2677 : #endif
2678 :
2679 : /**
2680 : Returns the number of references to this object. Available as of PLUMED 2.5.
2681 : \note Equivalent to plumed_use_count()
2682 : */
2683 : int useCount() const __PLUMED_WRAPPER_CXX_NOEXCEPT {
2684 : return plumed_use_count(main);
2685 : }
2686 :
2687 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
2688 : /**
2689 : Check if global-plumed has been initialized
2690 : \return true if global plumed object (see global()) is initialized (i.e. if gcreate() has been
2691 : called), false otherwise.
2692 : \note Equivalent to plumed_ginitialized() but returns a bool
2693 : */
2694 : static bool ginitialized() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2695 : return plumed_ginitialized();
2696 : }
2697 : /**
2698 : Check if global-plumed is valid
2699 : \return true if global plumed object (see global()) is valid.
2700 : \note Equivalent to plumed_gvalid() but returns a bool
2701 : */
2702 : static bool gvalid() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2703 : return plumed_gvalid();
2704 : }
2705 : /**
2706 : Initialize global-plumed.
2707 : \warning Using the global objects in C++ is not recommended since they are difficult to use in
2708 : an exception safe manner. In particular, one should explicitly catch exceptions to
2709 : properly call gfinalize()
2710 : \note Equivalent to plumed_gcreate()
2711 : */
2712 : static void gcreate() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2713 : plumed_gcreate();
2714 : }
2715 : /**
2716 : Send a command to global-plumed
2717 : \param key The name of the command to be executed
2718 : \note Equivalent to plumed_gcmd()
2719 : */
2720 : static void gcmd(const char*key) {
2721 : global().cmd(key);
2722 : }
2723 :
2724 : #if __cplusplus > 199711L
2725 :
2726 : /**
2727 : Send a command to global-plumed.
2728 : */
2729 : template<typename T>
2730 : static void gcmd(const char*key,T&& val) {
2731 : global().cmd(key,std::forward<T>(val));
2732 : }
2733 :
2734 : /**
2735 : Send a command to global-plumed.
2736 : This version detects passing size or shape as a pointer.
2737 : */
2738 : template<typename T,typename M>
2739 : static void gcmd(const char*key,T* val, M&& more) {
2740 : global().cmd(key,val,std::forward<M>(more));
2741 : }
2742 :
2743 : /**
2744 : Send a command to global-plumed.
2745 : This version detects passing shape as an initializer_list.
2746 : */
2747 : template<typename T>
2748 : static void gcmd(const char*key,T* val, std::initializer_list<SizeLike> shape) {
2749 : global().cmd(key,val,shape);
2750 : }
2751 :
2752 : #else
2753 :
2754 : /**
2755 : Send a command to global-plumed
2756 : \param key The name of the command to be executed
2757 : \param val The argument.
2758 : \note Equivalent to plumed_gcmd()
2759 : */
2760 : template<typename T>
2761 : static void gcmd(const char*key,T val) {
2762 : global().cmd(key,val);
2763 : }
2764 : /**
2765 : Send a command to global-plumed
2766 : \param key The name of the command to be executed
2767 : \param val The argument.
2768 : \param nelem Number of elements in the passed array, for typechecking.
2769 : \note Equivalent to plumed_gcmd()
2770 : */
2771 : template<typename T>
2772 : static void gcmd(const char*key,T* val,__PLUMED_WRAPPER_STD size_t nelem) {
2773 : global().cmd(key,val,nelem);
2774 : }
2775 :
2776 : /**
2777 : Send a command to global-plumed
2778 : \param key The name of the command to be executed
2779 : \param val The argument.
2780 : \param shape The shape of the argument.
2781 : \note Equivalent to plumed_gcmd()
2782 : */
2783 : template<typename T>
2784 : static void gcmd(const char*key,T* val, const __PLUMED_WRAPPER_STD size_t* shape) {
2785 : global().cmd(key,val,shape);
2786 : }
2787 :
2788 : #endif
2789 :
2790 : /**
2791 : Finalize global-plumed
2792 : */
2793 : static void gfinalize() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2794 : plumed_gfinalize();
2795 : }
2796 : /**
2797 : Returns the Plumed global object
2798 :
2799 : Notice that the object is copied, thus increasing the reference counter of the
2800 : global object. In this manner, the global object will survive after a call to
2801 : \ref gfinalize() if the resulting object is still in scope.
2802 :
2803 : \return The Plumed global object
2804 : */
2805 : static Plumed global() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2806 : return Plumed(plumed_global());
2807 : }
2808 : #endif /*}*/
2809 : /**
2810 : Constructor.
2811 :
2812 : Notice that when using runtime binding the constructed object might be
2813 : invalid. One might check it using the \ref valid() method.
2814 :
2815 : \note Performs the same task a plumed_create()
2816 : */
2817 5364 : Plumed()__PLUMED_WRAPPER_CXX_NOEXCEPT :
2818 : #if __PLUMED_WRAPPER_CXX_DEFAULT_INVALID
2819 : main(plumed_create_invalid())
2820 : #else
2821 5364 : main(plumed_create())
2822 : #endif
2823 : {
2824 : }
2825 :
2826 : /**
2827 : Clone a Plumed object from a FORTRAN char* handler.
2828 :
2829 : \param c The FORTRAN handler (a char[32]).
2830 :
2831 : The reference counter for the corresponding object will be increased
2832 : to make sure that the object will be available after plumed_f_finalize is called
2833 : if the created object is still in scope.
2834 : */
2835 : __PLUMED_WRAPPER_CXX_EXPLICIT Plumed(const char*c)__PLUMED_WRAPPER_CXX_NOEXCEPT :
2836 : main(plumed_create_reference_f(c)) {
2837 : }
2838 :
2839 : /**
2840 : Create a reference from a void* pointer. Available as of PLUMED 2.5.
2841 : */
2842 : __PLUMED_WRAPPER_CXX_EXPLICIT Plumed(void*v)__PLUMED_WRAPPER_CXX_NOEXCEPT :
2843 : main(plumed_create_reference_v(v)) {
2844 : }
2845 :
2846 : /**
2847 : Clone a Plumed object from a C plumed structure
2848 :
2849 : \param p The C plumed structure.
2850 :
2851 : The reference counter for the corresponding object will be increased
2852 : to make sure that the object will be available after plumed_finalize is called
2853 : if the created object is still in scope.
2854 : */
2855 : __PLUMED_WRAPPER_CXX_EXPLICIT Plumed(plumed p)__PLUMED_WRAPPER_CXX_NOEXCEPT :
2856 : main(plumed_create_reference(p)) {
2857 : }
2858 :
2859 : /** Copy constructor.
2860 :
2861 : Takes a reference, incrementing the reference counter of the corresponding object.
2862 : */
2863 : Plumed(const Plumed& p)__PLUMED_WRAPPER_CXX_NOEXCEPT :
2864 : main(plumed_create_reference(p.main)) {
2865 : }
2866 :
2867 : /** Assignment operator. Available as of PLUMED 2.5.
2868 :
2869 : Takes a reference,incrementing the reference counter of the corresponding object.
2870 : */
2871 : Plumed&operator=(const Plumed&p) __PLUMED_WRAPPER_CXX_NOEXCEPT {
2872 : if(this != &p) {
2873 : // the check is needed to avoid calling plumed_finalize on moved objects
2874 : if(main.p) {
2875 : plumed_finalize(main);
2876 : }
2877 : main=plumed_create_reference(p.main);
2878 : }
2879 : return *this;
2880 : }
2881 :
2882 : /*
2883 : PLUMED >= 2.4 requires a C++11 compiler.
2884 : Anyway, since Plumed.h file might be redistributed with other codes
2885 : and it should be possible to combine it with earlier PLUMED versions,
2886 : we here explicitly check if C+11 is available before enabling move semantics.
2887 : */
2888 : #if __cplusplus > 199711L
2889 : /** Move constructor. Available as of PLUMED 2.5.
2890 : Only if move semantics is enabled.
2891 : */
2892 : Plumed(Plumed&&p)__PLUMED_WRAPPER_CXX_NOEXCEPT :
2893 : main(p.main) {
2894 : p.main.p=nullptr;
2895 : }
2896 : /** Move assignment. Available as of PLUMED 2.5.
2897 : Only if move semantics is enabled.
2898 : */
2899 : Plumed& operator=(Plumed&&p)__PLUMED_WRAPPER_CXX_NOEXCEPT {
2900 : if(this != &p) {
2901 : // the check is needed to avoid calling plumed_finalize on moved objects
2902 : if(main.p) {
2903 : plumed_finalize(main);
2904 : }
2905 : main=p.main;
2906 : p.main.p=nullptr;
2907 : }
2908 : return *this;
2909 : }
2910 : #endif
2911 : /**
2912 : Create a PLUMED object loading a specific kernel. Available as of PLUMED 2.5.
2913 :
2914 : It returns an object created with \ref plumed_create_dlopen. The object is owned and
2915 : is then finalized in the destructor. It can be used as follows:
2916 : \verbatim
2917 : PLMD::Plumed p = PLMD::Plumed::dlopen("/path/to/libplumedKernel.so");
2918 : // or, equivalenty:
2919 : // PLMD::Plumed p(PLMD::Plumed::dlopen("/path/to/libplumedKernel.so"));
2920 : p.cmd("init");
2921 : \endverbatim
2922 : or, equivalently, as
2923 : \verbatim
2924 : auto p = PLMD::Plumed::dlopen("/path/to/libplumedKernel.so");
2925 : p.cmd("init");
2926 : \endverbatim
2927 : */
2928 : static Plumed dlopen(const char* path)__PLUMED_WRAPPER_CXX_NOEXCEPT {
2929 : plumed p=plumed_create_dlopen(path);
2930 : Plumed pp(p);
2931 : plumed_finalize(p);
2932 : return pp;
2933 : }
2934 :
2935 : /**
2936 : Create a PLUMED object loading a specific kernel. Available as of PLUMED 2.5.
2937 :
2938 : Same as \ref dlopen(const char* path), but allows a dlopen mode to be chosen explicitly.
2939 : */
2940 : static Plumed dlopen(const char* path,int mode)__PLUMED_WRAPPER_CXX_NOEXCEPT {
2941 : plumed p=plumed_create_dlopen2(path,mode);
2942 : Plumed pp(p);
2943 : plumed_finalize(p);
2944 : return pp;
2945 : }
2946 : /**
2947 : Create a PLUMED object loading from an already opened shared library. Available as of PLUMED 2.8.
2948 :
2949 : Same as \ref dlopen(const char* path), but searches functions in an already loaded library.
2950 : See \ref plumed_create_dlsym.
2951 : */
2952 : static Plumed dlsym(void* dlhandle)__PLUMED_WRAPPER_CXX_NOEXCEPT {
2953 : plumed p=plumed_create_dlsym(dlhandle);
2954 : Plumed pp(p);
2955 : plumed_finalize(p);
2956 : return pp;
2957 : }
2958 :
2959 : /** Invalid constructor. Available as of PLUMED 2.5.
2960 :
2961 : Can be used to initialize an invalid object. It might be useful to postpone
2962 : the initialization of a Plumed object. Consider the following case
2963 : \verbatim
2964 : Plumed p;
2965 : setenv("PLUMED_KERNEL","/path/to/kernel/libplumedKernel.so",1);
2966 : p.cmd("init")
2967 : \endverbatim
2968 : Here the `p` object will be initialized *before* the `PLUMED_KERNEL` env var has been set.
2969 : This can be particularly problematic if `p` is stored in some high level class.
2970 : The following case would do the job
2971 : \verbatim
2972 : Plumed p;
2973 : setenv("PLUMED_KERNEL","/path/to/kernel/libplumedKernel.so",1);
2974 : p=Plumed();
2975 : p.cmd("init")
2976 : \endverbatim
2977 : However, there will be some error reported related to the attempt to load the kernel
2978 : when `p` is initialized. The following solution is the optimal one:
2979 : \verbatim
2980 : Plumed p(Plumed::makeInvalid());
2981 : setenv("PLUMED_KERNEL","/path/to/kernel/libplumedKernel.so",1);
2982 : p=Plumed();
2983 : p.cmd("init")
2984 : \endverbatim
2985 : */
2986 : static Plumed makeInvalid() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2987 : plumed p=plumed_create_invalid();
2988 : Plumed pp(p);
2989 : plumed_finalize(p);
2990 : return pp;
2991 : }
2992 :
2993 : /**
2994 : Create a valid PLMD::Plumed object.
2995 :
2996 : Can be used to create a valid object e.g. when Plumed.h was compiled with
2997 : `-D__PLUMED_WRAPPER_CXX_DEFAULT_INVALID`. For internal usage.
2998 : */
2999 :
3000 : static Plumed makeValid()__PLUMED_WRAPPER_CXX_NOEXCEPT {
3001 : plumed p=plumed_create();
3002 : Plumed pp(p);
3003 : plumed_finalize(p);
3004 : return pp;
3005 : }
3006 :
3007 :
3008 : /**
3009 : Retrieve the C plumed structure for this object.
3010 :
3011 : Notice that the resulting plumed structure is a weak reference and
3012 : should NOT be finalized, unless a new reference is explicitly added
3013 : \verbatim
3014 : Plumed p;
3015 : plumed c=p;
3016 : plumed_finalize(c); // <- this is wrong
3017 : \endverbatim
3018 : \verbatim
3019 : Plumed p;
3020 : plumed c=plumed_create_reference(p);
3021 : plumed_finalize(c); // <- this is right
3022 : \endverbatim
3023 : */
3024 : operator plumed()const __PLUMED_WRAPPER_CXX_NOEXCEPT {
3025 : return main;
3026 : }
3027 :
3028 : /**
3029 : Retrieve a FORTRAN handler for this object
3030 : \param c The FORTRAN handler (a char[32]).
3031 : Notice that the resulting plumed structure is a weak reference and
3032 : should NOT be finalized, unless a new reference is explicitly added.
3033 : */
3034 : void toFortran(char*c)const __PLUMED_WRAPPER_CXX_NOEXCEPT {
3035 : plumed_c2f(main,c);
3036 : }
3037 :
3038 : /**
3039 : Retrieve a void* handler for this object. Available as of PLUMED 2.5.
3040 : Notice that the resulting plumed structure is a weak reference and
3041 : should NOT be finalized, unless a new reference is explicitly added.
3042 : */
3043 : void* toVoid()const __PLUMED_WRAPPER_CXX_NOEXCEPT {
3044 : return plumed_c2v(main);
3045 : }
3046 :
3047 : /**
3048 : Increase reference counter. Available as of PLUMED 2.5.
3049 :
3050 : Using this method improperly might interfere with correct object construction
3051 : and destruction.
3052 : If you want to play with this, also try to compile using `-D__PLUMED_WRAPPER_DEBUG_REFCOUNT=1` and see what happens.
3053 :
3054 : A possible usage is to transfer the ownership of a temporary
3055 : object when it is converted
3056 : \verbatim
3057 : plumed p=Plumed::dlopen(path).incref()
3058 : // without incref(), the just constructed object will be destroyed
3059 : // when the temporary object is deleted.
3060 : ... do stuff ...
3061 : plumed_finalize(p);
3062 : \endverbatim
3063 :
3064 : */
3065 : Plumed& incref() __PLUMED_WRAPPER_CXX_NOEXCEPT {
3066 : plumed_create_reference(main);
3067 : return *this;
3068 : }
3069 :
3070 : /**
3071 : Decrease reference counter. Available as of PLUMED 2.5.
3072 :
3073 : Using this method improperly might interfere with correct object construction
3074 : and destruction.
3075 : If you want to play with this, also try to compile using `-D__PLUMED_WRAPPER_DEBUG_REFCOUNT=1` and see what happens.
3076 : */
3077 : Plumed& decref() __PLUMED_WRAPPER_CXX_NOEXCEPT {
3078 : // calling decref on a moved plumed object should give an error, so we do not check if main.p!=NULL here:
3079 : plumed_finalize(main);
3080 : return *this;
3081 : }
3082 :
3083 : private:
3084 :
3085 : /**
3086 : Private version of cmd. It is used here to avoid duplication of code between typesafe and not-typesafe versions
3087 : */
3088 16675 : static void cmd_priv(plumed main,const char*key, SafePtr& safe, plumed_error*error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3089 :
3090 : plumed_error error_cxx;
3091 : plumed_error_init(&error_cxx);
3092 :
3093 : plumed_nothrow_handler nothrow;
3094 16675 : if(error) {
3095 : plumed_error_init(error);
3096 0 : nothrow.ptr=error;
3097 : } else {
3098 16675 : nothrow.ptr=&error_cxx;
3099 : }
3100 16675 : nothrow.handler=plumed_error_set;
3101 :
3102 : try {
3103 16675 : plumed_cmd_safe_nothrow(main,key,safe.get_safeptr(),nothrow);
3104 0 : } catch (...) {
3105 : assert(error_cxx.code==0); /* no need to plumed_error_finalize here */
3106 : /*
3107 : When loading a kernel <=2.4, plumed_cmd_nothrow could throw an exception.
3108 : If the exception is transmitted through the C interface and arrives here,
3109 : we translate it so as to free the virtual tables of the loaded kernel.
3110 : */
3111 0 : rethrow();
3112 0 : }
3113 : /* plumed_error_rethrow is finalizing */
3114 16675 : if(!error && error_cxx.code!=0) {
3115 : plumed_error_rethrow_cxx(error_cxx);
3116 : }
3117 16675 : }
3118 :
3119 : public:
3120 :
3121 : #if __cplusplus > 199711L
3122 :
3123 : private:
3124 :
3125 : // Small class to manage termination of string_view.
3126 : // The class has a SSO with size 128, so that most messages should fit without
3127 : // any allocation
3128 : class CString {
3129 : /// local buffer (fast)
3130 : char static_buffer[128];
3131 : /// dynamic buffer (requires allocation)
3132 : std::unique_ptr<char[]> dynamic_buffer;
3133 : /// actual pointer
3134 : const char * str;
3135 : /// Move constructor is deleted
3136 : CString(CString&&) = delete;
3137 : /// Move assignment operator is deleted
3138 : CString& operator=(CString&&) = delete;
3139 : public:
3140 : /// Initialize from a const char*, copying the address
3141 : CString(const char* str) noexcept {
3142 : this->str=str;
3143 : this->static_buffer[0]='\0';
3144 : }
3145 : /// Initialize from a std:string, taking the address of the corresponding c_str
3146 : CString(const std::string & str) noexcept {
3147 : this->str=str.c_str();
3148 : this->static_buffer[0]='\0';
3149 : }
3150 : #if __cplusplus >= 201703L
3151 : /// Initialize from a std::string_view, only C++17
3152 : /// Add a null terminator. If possible, use a local buffer, other wise allocate one.
3153 : CString(std::string_view str) {
3154 : std::size_t len=str.length();
3155 : char* buffer;
3156 : if(sizeof(static_buffer)>=len+1) {
3157 : // in this case, the string_view fits in the local buffer
3158 : buffer=static_buffer;
3159 : } else {
3160 : // in this case, the string_view does not fit in the local buffer
3161 : // hence we allocate a unique_ptr
3162 : dynamic_buffer=std::make_unique<char[]>(len+1);
3163 : buffer=dynamic_buffer.get();
3164 : }
3165 : // at this point, buffer is guaranteed to have size >= len+1
3166 : str.copy(buffer,len);
3167 : buffer[len]='\0'; // ensure null termination
3168 : this->str=buffer;
3169 : this->static_buffer[0]='\0';
3170 : }
3171 : #endif
3172 : operator const char* () const noexcept {
3173 : return str;
3174 : }
3175 : };
3176 :
3177 : /// Internal tool to convert initializer_list to shape
3178 : /// This is just taking an initializer list and making a std::array
3179 5364 : std::array<std::size_t,5> make_shape(std::initializer_list<SizeLike> shape) {
3180 5364 : if(shape.size()>4) {
3181 0 : throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3182 : }
3183 : std::array<std::size_t,5> shape_;
3184 : unsigned j=0;
3185 10728 : for(auto i : shape) {
3186 5364 : shape_[j]=i.size;
3187 5364 : j++;
3188 : }
3189 5364 : shape_[j]=0;
3190 5364 : return shape_;
3191 : }
3192 :
3193 : /// Internal utility to append a shape.
3194 : /// Create a new shape where newindex has been appended to the last non zero element.
3195 : std::array<std::size_t,5> append_size(std::size_t* shape,std::size_t newindex) {
3196 : std::array<std::size_t,5> shape_;
3197 : unsigned i;
3198 : for(i=0; i<4; i++) {
3199 : shape_[i]=shape[i];
3200 : if(shape[i]==0) {
3201 : break;
3202 : }
3203 : } // one less because we need to append another number!
3204 : if(i==4) {
3205 : throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3206 : }
3207 : shape_[i]=newindex;
3208 : shape_[i+1]=0;
3209 : return shape_;
3210 : }
3211 :
3212 : /// Helper functions for interpreting commands. **They are all internals**.
3213 : /// cmd_helper is called when we have no shape information associated.
3214 : /// cmd_helper_with_shape is called when we have shape information associated.
3215 : /// cmd_helper_with_nelem is called when we have size information associated.
3216 : /// The nocopy bool tells us if this pointer is pointing to a temporary variable, it is propagated by the cmd_helper_with_shape version
3217 : /// It makes sure PLUMED will not keep a copy.
3218 : /// The variants below change for the type of the val argument
3219 : /// There is a chain of SFINAE conditions. This would be better implement with if constexpr, but we avoid doing so
3220 : /// to keep this compatible with C++11.
3221 :
3222 : /// cmd_helper with custom array val (includes std::array)
3223 : /// temporaries are detected and the information is propragated
3224 : template<typename Key,typename T, typename std::enable_if<wrapper::is_custom_array<typename std::remove_reference<T>::type>::value, int>::type = 0>
3225 : void cmd_helper(Key && key,T&& val) {
3226 : std::size_t shape[] { wrapper::custom_array_size<T>(), 0 };
3227 : cmd_helper_with_shape(std::forward<Key>(key),wrapper::custom_array_cast(&val),shape, std::is_rvalue_reference<T&&>::value);
3228 : }
3229 :
3230 : /// cmd_helper with size/data val (typically, std::vector, std::string, small_vector, etc)
3231 : /// temporaries are detected and the information is propragated
3232 : template<typename Key,typename T, typename std::enable_if<!wrapper::is_custom_array<typename std::remove_reference<T>::type>::value && wrapper::has_size_and_data<T>::value, int>::type = 0>
3233 : void cmd_helper(Key && key,T&& val) {
3234 : std::size_t shape[] { wrapper::size(val), 0 };
3235 : cmd_helper_with_shape(std::forward<Key>(key),val.data(),shape, std::is_rvalue_reference<T&&>::value);
3236 : }
3237 :
3238 : /// cmd_helper with raw pointer val
3239 : /// temporaries are not detected. We can indeed save the pointer, even if it's a temporary as it is in the case cmd("a",&a)
3240 : /// here we use std::remove_reference to detect properly pointers to arrays
3241 : template<typename Key,typename T, typename std::enable_if<!wrapper::is_custom_array<typename std::remove_reference<T>::type>::value && !wrapper::has_size_and_data<T>::value && std::is_pointer<typename std::remove_reference<T>::type>::value, int>::type = 0>
3242 11089 : void cmd_helper(Key && key,T&& val) {
3243 : #if __PLUMED_WRAPPER_CXX_DETECT_SHAPES_STRICT
3244 : // this would be strict checking
3245 : // "a pointer without a specified size is meant to be pointing to a size 1 object"
3246 : std::size_t shape[] { 0, 0 };
3247 : if(val) {
3248 : shape[0]=1;
3249 : }
3250 : cmd_helper_with_shape(std::forward<Key>(key),val,shape);
3251 : #else
3252 : if(wrapper::is_custom_array<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value) {
3253 : // if we are passing a pointer to a fixed sized array, we make sure to retain the information related to
3254 : // the rank of the array and the following (fixed) dimensions
3255 : std::size_t shape[] { 0, 0 };
3256 : if(val) {
3257 : shape[0]=std::numeric_limits<std::size_t>::max();
3258 : }
3259 : cmd_helper_with_shape(std::forward<Key>(key),val,shape);
3260 : } else {
3261 : // otherwise, for backward compatibility, the pointer is assumed with no shape information
3262 11089 : SafePtr s(val,0,nullptr);
3263 11089 : cmd_priv(main,CString(key),s);
3264 : }
3265 : #endif
3266 11089 : }
3267 :
3268 : /// cmd_helper in remaining cases, that is when val is passed by value
3269 : /// temporaries are not detected. However, the argument is passed by value and its address is not copyable anyway
3270 : template<typename Key,typename T, typename std::enable_if<!wrapper::is_custom_array<typename std::remove_reference<T>::type>::value && !wrapper::has_size_and_data<T>::value && !std::is_pointer<typename std::remove_reference<T>::type>::value, int>::type = 0>
3271 : void cmd_helper(Key && key,T&& val) {
3272 : SafePtr s(val,0,nullptr);
3273 : cmd_priv(main,CString(key),s);
3274 : }
3275 :
3276 : /// cmd_helper_with_shape with custom array val (includes std::array and C arrays)
3277 : /// nocopy information is propagated
3278 : template<typename Key,typename T, typename std::enable_if<wrapper::is_custom_array<T>::value, int>::type = 0>
3279 : void cmd_helper_with_shape(Key && key,T* val, __PLUMED_WRAPPER_STD size_t* shape,bool nocopy=false) {
3280 : auto newptr=wrapper::custom_array_cast(val);
3281 : auto newshape=append_size(shape,wrapper::custom_array_size<T>());
3282 : cmd_helper_with_shape(std::forward<Key>(key),newptr,newshape.data(),nocopy);
3283 : }
3284 :
3285 : /// cmd_helper_with_shape with pointer to simple type val.
3286 : /// nocopy information is used to pass the proper flags to plumed
3287 : template<typename Key,typename T, typename std::enable_if<!wrapper::is_custom_array<T>::value, int>::type = 0>
3288 5364 : void cmd_helper_with_shape(Key && key,T* val, __PLUMED_WRAPPER_STD size_t* shape,bool nocopy=false) {
3289 : SafePtr s(val,0,shape);
3290 5364 : if(nocopy) {
3291 0 : s.safe.flags |= 0x10000000;
3292 : }
3293 5364 : cmd_priv(main,CString(key),s);
3294 5364 : }
3295 :
3296 : #if ! __PLUMED_WRAPPER_CXX_DETECT_SHAPES_STRICT
3297 : /// cmd_helper_with_nelem with custom array val (includes std::array)
3298 : /// this helper is only used for backward compatibility, so it does not need to take into account
3299 : /// the copyability of the pointer
3300 : template<typename Key,typename T, typename std::enable_if<wrapper::is_custom_array<T>::value, int>::type = 0>
3301 : void cmd_with_nelem(Key && key,T* val, __PLUMED_WRAPPER_STD size_t nelem) {
3302 : std::size_t shape[] { 0, 0 };
3303 : if(val) {
3304 : shape[0]=nelem;
3305 : }
3306 : cmd_helper_with_shape(std::forward<Key>(key),val,shape);
3307 : }
3308 :
3309 : /// cmd_helper_with_nelem with pointer to simple type val.
3310 : /// this helper is only used for backward compatibility, so it does not need to take into account
3311 : /// the copyability of the pointer
3312 : template<typename Key,typename T, typename std::enable_if<!wrapper::is_custom_array<T>::value, int>::type = 0>
3313 : void cmd_with_nelem(Key && key,T* val, __PLUMED_WRAPPER_STD size_t nelem) {
3314 : // pointer, directly managed by SafePtr
3315 : SafePtr s(val,nelem,nullptr);
3316 : cmd_priv(main,CString(key),s);
3317 : }
3318 : #endif
3319 :
3320 : public:
3321 :
3322 : /**
3323 : Send a command to this plumed object
3324 : \param key The name of the command to be executed
3325 : \note Similar to \ref plumed_cmd(). It actually called \ref plumed_cmd_nothrow() and
3326 : rethrow any exception raised within PLUMED.
3327 : */
3328 : template<typename Key>
3329 : void cmd(Key && key) {
3330 : SafePtr s;
3331 : cmd_priv(main,CString(key),s);
3332 : }
3333 :
3334 : /**
3335 : Send a command to this plumed object
3336 : \param key The name of the command to be executed
3337 : \param val The argument.
3338 : */
3339 : template<typename Key,typename T>
3340 : void cmd(Key && key,T&& val) {
3341 11089 : cmd_helper(std::forward<Key>(key),std::forward<T>(val));
3342 11089 : }
3343 :
3344 : /**
3345 : Send a command to this plumed object
3346 : \param key The name of the command to be executed
3347 : \param val The argument.
3348 : \note This overload accepts a pointer and corresponding size
3349 : information. It's usage is discouraged:
3350 : the overload accepting shape information should be preferred.
3351 : */
3352 :
3353 : template<typename Key,typename T, typename I, typename std::enable_if<std::is_integral<I>::value, int>::type = 0>
3354 : void cmd(Key && key,T* val, I nelem) {
3355 : #if __PLUMED_WRAPPER_CXX_DETECT_SHAPES_STRICT
3356 : static_assert("in strict mode you cannot pass nelem, please pass full shape instead");
3357 : #else
3358 : cmd_with_nelem(std::forward<Key>(key),val,__PLUMED_WRAPPER_STD size_t(nelem));
3359 : #endif
3360 : }
3361 :
3362 : /**
3363 : Send a command to this plumed object
3364 : \param key The name of the command to be executed
3365 : \param val The argument.
3366 : \note This overload accepts a pointer and corresponding shape
3367 : information. Shape is passed a size_t pointer,
3368 : but the overload accepting an initializer_list
3369 : has a more friendly syntax.
3370 : */
3371 : template<typename Key,typename T>
3372 : void cmd(Key && key,T* val, __PLUMED_WRAPPER_STD size_t* shape) {
3373 : unsigned i;
3374 : for(i=0; i<5; i++)
3375 : if(shape[i]==0) {
3376 : break;
3377 : }
3378 : if(i==5) {
3379 : throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3380 : }
3381 : cmd_helper_with_shape(std::forward<Key>(key),val,shape);
3382 : }
3383 :
3384 : /**
3385 : Send a command to this plumed object
3386 : \param key The name of the command to be executed
3387 : \param val The argument.
3388 : \note This overload accepts a pointer and corresponding shape
3389 : information. Shape is passed a size_t pointer,
3390 : but the overload accepting an initializer_list
3391 : has a more friendly syntax.
3392 : */
3393 : template<typename Key,typename T>
3394 5364 : void cmd(Key && key,T* val, std::initializer_list<SizeLike> shape) {
3395 5364 : auto shape_=make_shape(shape);
3396 5364 : cmd_helper_with_shape(std::forward<Key>(key),val,shape_.data());
3397 5364 : }
3398 :
3399 : public:
3400 :
3401 : #else
3402 :
3403 : /**
3404 : Send a command to this plumed object
3405 : \param key The name of the command to be executed
3406 : \note Similar to \ref plumed_cmd(). It actually called \ref plumed_cmd_nothrow() and
3407 : rethrow any exception raised within PLUMED.
3408 : */
3409 : void cmd(const char*key) {
3410 : plumed_cmd_cxx(main,key);
3411 : }
3412 :
3413 :
3414 : /**
3415 : Send a command to this plumed object
3416 : \param key The name of the command to be executed
3417 : \param val The argument, passed by value.
3418 : \note Similar to \ref plumed_cmd(). It actually called \ref plumed_cmd_nothrow() and
3419 : rethrow any exception raised within PLUMED.
3420 : \note Unless PLUMED library is <=2.7,
3421 : the type of the argument is checked.
3422 : */
3423 : template<typename T>
3424 : void cmd(const char*key,T val) {
3425 : plumed_cmd_cxx(main,key,val);
3426 : }
3427 :
3428 : /**
3429 : Send a command to this plumed object
3430 : \param key The name of the command to be executed
3431 : \param val The argument, passed by pointer.
3432 : \param shape A zero-terminated array containing the shape of the data.
3433 : \note Similar to \ref plumed_cmd(). It actually called \ref plumed_cmd_nothrow() and
3434 : rethrow any exception raised within PLUMED.
3435 : \note Unless PLUMED library is <=2.7,
3436 : the type of the argument is checked. If shape is passed, it is also
3437 : checked that PLUMED access only compatible indexes.
3438 : */
3439 : template<typename T>
3440 : void cmd(const char*key,T* val, const __PLUMED_WRAPPER_STD size_t* shape) {
3441 : unsigned i;
3442 : for(i=0; i<5; i++)
3443 : if(shape[i]==0) {
3444 : break;
3445 : }
3446 : if(i==5) {
3447 : throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3448 : }
3449 : plumed_cmd_cxx(main,key,val,shape);
3450 : }
3451 :
3452 : /**
3453 : Send a command to this plumed object
3454 : \param key The name of the command to be executed
3455 : \param val The argument, passed by pointer.
3456 : \param nelem The number of elements passed.
3457 : \note Similar to \ref plumed_cmd(). It actually called \ref plumed_cmd_nothrow() and
3458 : rethrow any exception raised within PLUMED.
3459 : \note Unless PLUMED library is <=2.7,
3460 : the type of the argument is checked. nelem is used to check
3461 : the maximum index interpreting the array as flattened.
3462 : */
3463 : template<typename T>
3464 : void cmd(const char*key,T* val, __PLUMED_WRAPPER_STD size_t nelem) {
3465 : plumed_cmd_cxx(main,key,val,nelem);
3466 : }
3467 :
3468 : #endif
3469 :
3470 :
3471 : /**
3472 : Destructor
3473 :
3474 : It calls \ref plumed_finalize(). Notice that this is done also if the
3475 : constructor failed (that is, if it returned an invalid object). This allows
3476 : declaring Plumed objects also if PLUMED is actually not available, provided
3477 : one does not use the \ref cmd method.
3478 :
3479 : Destructor is virtual so as to allow correct inheritance from Plumed object.
3480 : */
3481 : #if __PLUMED_WRAPPER_CXX_POLYMORPHIC
3482 : virtual
3483 : #endif
3484 5364 : ~Plumed() __PLUMED_WRAPPER_CXX_NOEXCEPT {
3485 : // the check is needed to avoid calling plumed_finalize on moved objects
3486 5364 : if(main.p) {
3487 5364 : plumed_finalize(main);
3488 : }
3489 5364 : }
3490 :
3491 : /**
3492 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3493 : namely implement typechecks and rethrowing exception.
3494 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3495 : They are also used by the Plumed::cmd functions to avoid code duplication.
3496 : Available as of PLUMED 2.8.
3497 : */
3498 : static void plumed_cmd_cxx(plumed p,const char*key,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3499 : SafePtr s;
3500 : cmd_priv(p,key,s,error);
3501 : }
3502 :
3503 : /**
3504 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3505 : namely implement typechecks and rethrowing exception.
3506 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3507 : They are also used by the Plumed::cmd functions to avoid code duplication.
3508 : Available as of PLUMED 2.8.
3509 : */
3510 : template<typename T>
3511 222 : static void plumed_cmd_cxx(plumed p,const char*key,T val,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3512 : SafePtr s(val,0,__PLUMED_WRAPPER_CXX_NULLPTR);
3513 222 : cmd_priv(p,key,s,error);
3514 222 : }
3515 :
3516 : /**
3517 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3518 : namely implement typechecks and rethrowing exception.
3519 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3520 : They are also used by the Plumed::cmd functions to avoid code duplication.
3521 : Available as of PLUMED 2.8.
3522 : */
3523 : template<typename T>
3524 : static void plumed_cmd_cxx(plumed p,const char*key,T* val,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3525 : SafePtr s(val,0,__PLUMED_WRAPPER_CXX_NULLPTR);
3526 : cmd_priv(p,key,s,error);
3527 : }
3528 :
3529 : /**
3530 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3531 : namely implement typechecks and rethrowing exception.
3532 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3533 : They are also used by the Plumed::cmd functions to avoid code duplication.
3534 : Available as of PLUMED 2.8.
3535 : */
3536 : template<typename T>
3537 : static void plumed_cmd_cxx(plumed p,const char*key,T* val, __PLUMED_WRAPPER_STD size_t nelem,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3538 : SafePtr s(val,nelem,__PLUMED_WRAPPER_CXX_NULLPTR);
3539 : cmd_priv(p,key,s,error);
3540 : }
3541 :
3542 : /**
3543 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3544 : namely implement typechecks and rethrowing exception.
3545 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3546 : They are also used by the Plumed::cmd functions to avoid code duplication.
3547 : Available as of PLUMED 2.8.
3548 : */
3549 : template<typename T>
3550 : static void plumed_cmd_cxx(plumed p,const char*key,T* val, const __PLUMED_WRAPPER_STD size_t* shape,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3551 : unsigned i;
3552 : for(i=0; i<5; i++)
3553 : if(shape[i]==0) {
3554 : break;
3555 : }
3556 : if(i==5) {
3557 : throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3558 : }
3559 : SafePtr s(val,0,shape);
3560 : cmd_priv(p,key,s,error);
3561 : }
3562 :
3563 :
3564 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
3565 : /**
3566 : \related Plumed
3567 : This function can be used to make plumed_gcmd behave as the C++ wrapper PLMD::Plumed::gcmd,
3568 : namely implement typechecks and rethrowing exception.
3569 : To be used through the macro plumed_gcmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3570 : Available as of PLUMED 2.8.
3571 : */
3572 :
3573 : /**
3574 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3575 : namely implement typechecks and rethrowing exception.
3576 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3577 : They are also used by the Plumed::cmd functions to avoid code duplication.
3578 : Available as of PLUMED 2.8.
3579 : */
3580 : static void plumed_gcmd_cxx(const char*key,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3581 : plumed_cmd_cxx(plumed_global(),key,error);
3582 : }
3583 :
3584 : /**
3585 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3586 : namely implement typechecks and rethrowing exception.
3587 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3588 : They are also used by the Plumed::cmd functions to avoid code duplication.
3589 : Available as of PLUMED 2.8.
3590 : */
3591 : template<typename T>
3592 : static void plumed_gcmd_cxx(const char*key,T val,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3593 : plumed_cmd_cxx(plumed_global(),key,val,error);
3594 : }
3595 :
3596 : /**
3597 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3598 : namely implement typechecks and rethrowing exception.
3599 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3600 : They are also used by the Plumed::cmd functions to avoid code duplication.
3601 : Available as of PLUMED 2.8.
3602 : */
3603 : template<typename T>
3604 : static void plumed_gcmd_cxx(const char*key,T val, __PLUMED_WRAPPER_STD size_t nelem,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3605 : plumed_cmd_cxx(plumed_global(),key,val,nelem,error);
3606 : }
3607 :
3608 : /**
3609 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3610 : namely implement typechecks and rethrowing exception.
3611 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3612 : They are also used by the Plumed::cmd functions to avoid code duplication.
3613 : Available as of PLUMED 2.8.
3614 : */
3615 : template<typename T>
3616 : static void plumed_gcmd_cxx(const char*key,T val, const __PLUMED_WRAPPER_STD size_t* shape,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3617 : unsigned i;
3618 : for(i=0; i<5; i++)
3619 : if(shape[i]==0) {
3620 : break;
3621 : }
3622 : if(i==5) {
3623 : throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3624 : }
3625 : plumed_cmd_cxx(plumed_global(),key,val,shape,error);
3626 : }
3627 :
3628 : #endif /*}*/
3629 :
3630 : #if __PLUMED_WRAPPER_CXX_BIND_C /*{*/
3631 :
3632 : #define __PLUMED_WRAPPER_REDEFINE_CMD ::PLMD::Plumed::plumed_cmd_cxx
3633 :
3634 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
3635 : #define __PLUMED_WRAPPER_REDEFINE_GCMD ::PLMD::Plumed::plumed_gcmd_cxx
3636 : #endif /*}*/
3637 :
3638 : #define __PLUMED_WRAPPER_REDEFINE_ERROR_RETHROW ::PLMD::Plumed::plumed_error_rethrow_cxx
3639 :
3640 : #endif /*}*/
3641 :
3642 : };
3643 :
3644 : /**
3645 : \related Plumed
3646 : Comparison operator. Available as of PLUMED 2.5.
3647 : */
3648 : inline
3649 : bool operator==(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3650 : return a.toVoid()==b.toVoid();
3651 : }
3652 :
3653 : /**
3654 : \related Plumed
3655 : Comparison operator. Available as of PLUMED 2.5.
3656 : */
3657 : inline
3658 : bool operator!=(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3659 : return a.toVoid()!=b.toVoid();
3660 : }
3661 :
3662 : /**
3663 : \related Plumed
3664 : Comparison operator. Available as of PLUMED 2.5.
3665 : */
3666 : inline
3667 : bool operator<=(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3668 : return a.toVoid()<=b.toVoid();
3669 : }
3670 :
3671 : /**
3672 : \related Plumed
3673 : Comparison operator. Available as of PLUMED 2.5.
3674 : */
3675 : inline
3676 : bool operator<(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3677 : return a.toVoid()<b.toVoid();
3678 : }
3679 :
3680 : /**
3681 : \related Plumed
3682 : Comparison operator. Available as of PLUMED 2.5.
3683 : */
3684 : inline
3685 : bool operator>=(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3686 : return a.toVoid()>=b.toVoid();
3687 : }
3688 :
3689 : /**
3690 : \related Plumed
3691 : Comparison operator. Available as of PLUMED 2.5.
3692 : */
3693 : inline
3694 : bool operator>(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3695 : return a.toVoid()>b.toVoid();
3696 : }
3697 :
3698 : __PLUMED_WRAPPER_ANONYMOUS_END /*}*/
3699 :
3700 : }
3701 :
3702 : #endif /*}*/
3703 :
3704 : #endif /*}*/
3705 :
3706 : /* END OF DECLARATIONS */
3707 :
3708 : /*
3709 :
3710 : 1: emit implementation
3711 : 0: do not emit implementation
3712 :
3713 : Allows an implementation to be emitted together with the declarations.
3714 :
3715 : Used to decide if definitions should be emitted. This macro could have a different
3716 : value when Plumed.h is reincluded. As a consequence, we map it to a local
3717 : macro (__PLUMED_WRAPPER_IMPLEMENTATION_) that is reset at the end of this file.
3718 : */
3719 :
3720 : #ifdef __PLUMED_WRAPPER_IMPLEMENTATION
3721 : #define __PLUMED_WRAPPER_IMPLEMENTATION_ __PLUMED_WRAPPER_IMPLEMENTATION
3722 : #else
3723 : #define __PLUMED_WRAPPER_IMPLEMENTATION_ 0
3724 : #endif
3725 :
3726 : /* BEGINNING OF DEFINITIONS */
3727 :
3728 : #if __PLUMED_WRAPPER_IMPLEMENTATION_ /*{*/
3729 : #ifndef __PLUMED_wrapper_Plumed_implementation /*{*/
3730 : #define __PLUMED_wrapper_Plumed_implementation
3731 :
3732 : /*
3733 : the following macros only control the implementation
3734 : */
3735 :
3736 : /*
3737 : 1: enable the definition of plumed_symbol_table_reexport
3738 : 0: does not enable the definition of plumed_symbol_table_reexport
3739 :
3740 : This is only needed in the official plumed library to make
3741 : the symbol table available. This is a hack to reexport the function table
3742 : and is only needed when creating the library libplumed.so.
3743 : */
3744 :
3745 : #ifndef __PLUMED_WRAPPER_REEXPORT_SYMBOL_TABLE
3746 : #define __PLUMED_WRAPPER_REEXPORT_SYMBOL_TABLE 0
3747 : #endif
3748 :
3749 : /*
3750 : 1: write on stderr changes in reference counters
3751 : 0: do not write changes in reference counters
3752 :
3753 : Used for debugging.
3754 :
3755 : Only used in definitions.
3756 : */
3757 :
3758 : #ifndef __PLUMED_WRAPPER_DEBUG_REFCOUNT
3759 : #define __PLUMED_WRAPPER_DEBUG_REFCOUNT 0
3760 : #endif
3761 :
3762 : /*
3763 : 1: emit plumed_kernel_register function (default)
3764 : 0: do not emit plumed_kernel_register function
3765 :
3766 : This function is only needed to avoid an extra warning when loading old (<=2.4) kernels.
3767 : We might change its default in the future.
3768 :
3769 : Used only in definitions.
3770 : */
3771 :
3772 : #ifndef __PLUMED_WRAPPER_KERNEL_REGISTER
3773 : #define __PLUMED_WRAPPER_KERNEL_REGISTER 1
3774 : #endif
3775 :
3776 : /*
3777 : 1: emit Fortran wrappers
3778 : 0: do not emit Fortran wrappers (default)
3779 :
3780 : Used only in definitions.
3781 : */
3782 :
3783 : #ifndef __PLUMED_WRAPPER_FORTRAN
3784 : #define __PLUMED_WRAPPER_FORTRAN 0
3785 : #endif
3786 :
3787 : /*
3788 : With internal interface, it does not make sense to emit kernel register or fortran interfaces
3789 : */
3790 :
3791 : #if ! __PLUMED_WRAPPER_EXTERN /*{*/
3792 : #undef __PLUMED_WRAPPER_KERNEL_REGISTER
3793 : #define __PLUMED_WRAPPER_KERNEL_REGISTER 0
3794 : #undef __PLUMED_WRAPPER_FORTRAN
3795 : #define __PLUMED_WRAPPER_FORTRAN 0
3796 : #endif /*}*/
3797 :
3798 : #ifdef __PLUMED_HAS_DLOPEN
3799 : #include <dlfcn.h> /* dlopen dlerror dlsym */
3800 : #endif
3801 :
3802 : #if __PLUMED_WRAPPER_CXX_STD
3803 : #include <cstdio> /* fprintf */
3804 : #include <cstring> /* memcpy strlen strncpy memcmp memmove strcmp memcpy */
3805 : #include <cassert> /* assert */
3806 : #include <cstdlib> /* getenv malloc free abort */
3807 : #include <climits> /* CHAR_BIT */
3808 : #else
3809 : #include <stdio.h>
3810 : #include <string.h>
3811 : #include <assert.h>
3812 : #include <stdlib.h>
3813 : #include <limits.h>
3814 : #endif
3815 :
3816 : /**
3817 : Function pointer to plumed_create
3818 : */
3819 :
3820 : typedef void*(*plumed_create_pointer)(void);
3821 : /**
3822 : Function pointer to plumed_cmd
3823 : */
3824 : typedef void(*plumed_cmd_pointer)(void*,const char*,const void*);
3825 :
3826 : /**
3827 : Function pointer to plumed_finalize
3828 : */
3829 : typedef void(*plumed_finalize_pointer)(void*);
3830 :
3831 : /**
3832 : Holder for plumedmain function pointers.
3833 : */
3834 : typedef struct {
3835 : plumed_create_pointer create;
3836 : plumed_cmd_pointer cmd;
3837 : plumed_finalize_pointer finalize;
3838 : } plumed_plumedmain_function_holder;
3839 :
3840 : /**
3841 : Holder for plumed symbol table.
3842 :
3843 : The table contains pointers to function exported from plumed. Functions can be added increasing the version number.
3844 : Notice that the default way to extend functionalities is by adding cmd strings. This is a last resort, and all new
3845 : functions should be explicitly motivated. Here's the addition:
3846 :
3847 : version=2, cmd_nothrow.
3848 :
3849 : This function accepts an extra argument `plumed_nothrow_handler*handler`.
3850 : In case an exception is thrown within plumed, it just calls `handler->handler(handler->ptr,code,message,opt)` and return.
3851 : An alternative would have been to install an error handler (with a call to cmd("setErrorHandler")). However, the cost
3852 : of doing it everytime Plumed::cmd is called is too high. On the other hand, installing it only at object construction
3853 : is very risky since and object created in that way would not report any error if manipulated from the C interface.
3854 : So, it looks like this is the only possibility.
3855 :
3856 : version=3, cmd_safe and cmd_safe_nothrow
3857 :
3858 : These are functions that accept a plumed_safeptr object, which can carry information about the passed type and size.
3859 : Since new information should be passed at every cmd call, this can only be obtained by adding new cmd calls.
3860 :
3861 : version=4, thread-safe reference counter
3862 :
3863 : These functions allow to access a thread-safe reference counter that is stored within the PlumedMain object.
3864 : This allows avoiding to enable atomic access also the C compiler used build Plumed.c. It's added here and not as a new
3865 : cmd since this is a very low-level functionality.
3866 : */
3867 : typedef struct {
3868 : /**
3869 : Version number.
3870 :
3871 : Minimum value is 1.
3872 : */
3873 : int version;
3874 : /**
3875 : Pointers to standard plumed functions (create/cmd/finalize).
3876 :
3877 : Always available.
3878 : */
3879 : plumed_plumedmain_function_holder functions;
3880 : /**
3881 : Pointer to a cmd function guaranteed not to throw exceptions.
3882 :
3883 : Available with version>=2.
3884 : */
3885 : void (*cmd_nothrow)(void*plumed,const char*key,const void*val,plumed_nothrow_handler);
3886 : /**
3887 : Pointer to a cmd function that accepts typeinfos.
3888 :
3889 : Available with version>=3.
3890 : */
3891 : void (*cmd_safe)(void*plumed,const char*key,plumed_safeptr);
3892 :
3893 : /**
3894 : Pointer to a cmd function guaranteed not to throw exceptions and that accepts typeinfos.
3895 :
3896 : Available with version>=3.
3897 : */
3898 : void (*cmd_safe_nothrow)(void*plumed,const char*key,plumed_safeptr,plumed_nothrow_handler);
3899 :
3900 : /**
3901 : Pointer to a function that increments the internal reference counter.
3902 :
3903 : Available with version>=4.
3904 : */
3905 : unsigned (*create_reference)(void*);
3906 : /**
3907 : Pointer to a function that decrements the internal reference counter.
3908 :
3909 : Available with version>=4.
3910 : */
3911 : unsigned (*delete_reference)(void*);
3912 : /**
3913 : Pointer to a function that returns the internal reference counter.
3914 :
3915 : Available with version>=4.
3916 : */
3917 : unsigned (*use_count)(void*);
3918 : } plumed_symbol_table_type;
3919 :
3920 : /* Utility to convert function pointers to pointers, just for the sake of printing them */
3921 : #define __PLUMED_CONVERT_FPTR(ptr,fptr) { ptr=__PLUMED_WRAPPER_CXX_NULLPTR; __PLUMED_WRAPPER_STD memcpy(&ptr,&fptr,(sizeof(fptr)>sizeof(ptr)?sizeof(ptr):sizeof(fptr))); }
3922 :
3923 : #define __PLUMED_GETENV __PLUMED_WRAPPER_STD getenv
3924 : #define __PLUMED_FPRINTF __PLUMED_WRAPPER_STD fprintf
3925 :
3926 : /**
3927 : Historically (PLUMED<=2.4) register for plumedmain function pointers.
3928 : As of PLUMED>=2.5, this function does not do anything except for reporting the attempt to register
3929 : something. It always returns NULL. The function should be here anyway to allow an incomplete
3930 : libplumedKernel (<=2.4), expecting this function to be present, to be loaded correctly.
3931 : */
3932 : #if __PLUMED_WRAPPER_KERNEL_REGISTER
3933 : /* Since it is only called from outside, it must be hardcoded to be extern */
3934 : __PLUMED_WRAPPER_EXTERN_C_BEGIN /*{*/
3935 : extern plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder*);
3936 26 : plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder* f) {
3937 : void* tmpptr;
3938 26 : if(f) {
3939 26 : if(__PLUMED_GETENV("PLUMED_LOAD_DEBUG")) {
3940 0 : __PLUMED_FPRINTF(stderr,"+++ Ignoring registration at %p (",__PLUMED_WRAPPER_STATIC_CAST(const void*,f));
3941 : __PLUMED_CONVERT_FPTR(tmpptr,f->create);
3942 0 : __PLUMED_FPRINTF(stderr,"%p,",tmpptr);
3943 : __PLUMED_CONVERT_FPTR(tmpptr,f->cmd);
3944 0 : __PLUMED_FPRINTF(stderr,"%p,",tmpptr);
3945 : __PLUMED_CONVERT_FPTR(tmpptr,f->finalize);
3946 0 : __PLUMED_FPRINTF(stderr,"%p) +++\n",tmpptr);
3947 : }
3948 : }
3949 26 : return __PLUMED_WRAPPER_CXX_NULLPTR;
3950 : }
3951 : __PLUMED_WRAPPER_EXTERN_C_END /*}*/
3952 : #endif
3953 :
3954 : #if defined( __PLUMED_HAS_DLOPEN) /*{*/
3955 : /**
3956 : Try to dlopen a path with a given mode.
3957 : If the dlopen command fails, it tries to strip the `Kernel` part of the name.
3958 :
3959 : This function is declared static (internal linkage) so that it is not visible from outside.
3960 : It is first declared then defined to make sure it is a regular C static function.
3961 : */
3962 :
3963 : __PLUMED_WRAPPER_INTERNALS_BEGIN
3964 9 : void* plumed_attempt_dlopen(const char*path,int mode) {
3965 : char* pathcopy;
3966 : void* p;
3967 : char* pc;
3968 : __PLUMED_WRAPPER_STD size_t strlenpath;
3969 : pathcopy=__PLUMED_WRAPPER_CXX_NULLPTR;
3970 : p=__PLUMED_WRAPPER_CXX_NULLPTR;
3971 : pc=__PLUMED_WRAPPER_CXX_NULLPTR;
3972 : strlenpath=0;
3973 9 : dlerror();
3974 9 : p=dlopen(path,mode);
3975 9 : if(!p) {
3976 : /*
3977 : Something went wrong. We try to remove "Kernel" string from the PLUMED_KERNEL variable
3978 : and load directly the shared library. Notice that this particular path is only expected
3979 : to be necessary when using PLUMED<=2.4 and the symbols in the main executable are
3980 : not visible. All the other cases (either PLUMED>=2.5 or symbols in the main executable visible)
3981 : should work correctly without entering here.
3982 : */
3983 0 : __PLUMED_FPRINTF(stderr,"+++ An error occurred. Message from dlopen(): %s +++\n",dlerror());
3984 0 : strlenpath=__PLUMED_WRAPPER_STD strlen(path);
3985 0 : pathcopy=__PLUMED_WRAPPER_STATIC_CAST(char*, plumed_malloc(strlenpath+1));
3986 0 : if(!pathcopy) {
3987 0 : __PLUMED_FPRINTF(stderr,"+++ Allocation error +++\n");
3988 0 : __PLUMED_WRAPPER_STD abort();
3989 : }
3990 : __PLUMED_WRAPPER_STD memcpy(pathcopy,path,strlenpath+1);
3991 0 : pc=pathcopy+strlenpath-6;
3992 0 : while(pc>=pathcopy && __PLUMED_WRAPPER_STD memcmp(pc,"Kernel",6)) {
3993 0 : pc--;
3994 : }
3995 0 : if(pc>=pathcopy) {
3996 0 : __PLUMED_WRAPPER_STD memmove(pc, pc+6, __PLUMED_WRAPPER_STD strlen(pc)-5);
3997 0 : __PLUMED_FPRINTF(stderr,"+++ This error is expected if you are trying to load a kernel <=2.4\n");
3998 0 : __PLUMED_FPRINTF(stderr,"+++ Trying %s +++\n",pathcopy);
3999 0 : dlerror();
4000 0 : p=dlopen(pathcopy,mode);
4001 0 : if(!p) {
4002 0 : __PLUMED_FPRINTF(stderr,"+++ An error occurred. Message from dlopen(): %s +++\n",dlerror());
4003 : }
4004 : }
4005 0 : plumed_free(pathcopy);
4006 : }
4007 9 : return p;
4008 : }
4009 : __PLUMED_WRAPPER_INTERNALS_END
4010 :
4011 : /**
4012 : Utility to search for a function.
4013 : */
4014 : #ifdef __cplusplus
4015 : #define __PLUMED_WRAPPER_SEARCHF_CAST(functype,func,tmpptr) func=reinterpret_cast<functype>(tmpptr)
4016 : #else
4017 : #define __PLUMED_WRAPPER_SEARCHF_CAST(functype,func,tmpptr) *(void **)&func=tmpptr
4018 : #endif
4019 : #define __PLUMED_SEARCH_FUNCTION(functype,tmpptr,handle,func,name,debug) \
4020 : if(!func) { \
4021 : tmpptr=dlsym(handle,name); \
4022 : if(tmpptr) { \
4023 : __PLUMED_WRAPPER_SEARCHF_CAST(functype,func,tmpptr); \
4024 : if(debug) __PLUMED_FPRINTF(stderr,"+++ %s found at %p +++\n",name,tmpptr); \
4025 : } else { \
4026 : if(debug) __PLUMED_FPRINTF(stderr,"+++ Function %s not found\n",name); \
4027 : } \
4028 : }
4029 :
4030 : /**
4031 : Search symbols in a dlopened library.
4032 :
4033 : This function is declared static (internal linkage) so that it is not visible from outside.
4034 : */
4035 : __PLUMED_WRAPPER_INTERNALS_BEGIN
4036 9 : void plumed_search_symbols(void* handle, plumed_plumedmain_function_holder* f,plumed_symbol_table_type** table) {
4037 : plumed_plumedmain_function_holder functions;
4038 : plumed_symbol_table_type* table_ptr;
4039 : void* tmpptr;
4040 : char* debug;
4041 : functions.create=__PLUMED_WRAPPER_CXX_NULLPTR;
4042 : functions.cmd=__PLUMED_WRAPPER_CXX_NULLPTR;
4043 : functions.finalize=__PLUMED_WRAPPER_CXX_NULLPTR;
4044 : table_ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
4045 9 : tmpptr=__PLUMED_WRAPPER_CXX_NULLPTR;
4046 : /*
4047 : Notice that as of PLUMED 2.5 we ignore self registrations.
4048 : Pointers are searched in the form of a single pointer to a structure, which
4049 : is the standard way in PLUMED 2.5, as well as using alternative names used in
4050 : PLUMED 2.0 to 2.4 (e.g. plumedmain_create) and in some intermediate versions between
4051 : PLUMED 2.4 and 2.5 (e.g. plumed_plumedmain_create). The last chance is probably
4052 : unnecessary and might be removed at some point.
4053 : */
4054 9 : debug=__PLUMED_GETENV("PLUMED_LOAD_DEBUG");
4055 9 : table_ptr=__PLUMED_WRAPPER_STATIC_CAST(plumed_symbol_table_type*, dlsym(handle,"plumed_symbol_table"));
4056 9 : if(table_ptr) {
4057 9 : functions=table_ptr->functions;
4058 : }
4059 9 : if(debug) {
4060 0 : if(table_ptr) {
4061 0 : __PLUMED_FPRINTF(stderr,"+++ plumed_symbol_table version %i found at %p +++\n",table_ptr->version,__PLUMED_WRAPPER_STATIC_CAST(void*,table_ptr));
4062 0 : __PLUMED_FPRINTF(stderr,"+++ plumed_function_pointers found at %p (",__PLUMED_WRAPPER_STATIC_CAST(void*,&table_ptr->functions));
4063 : __PLUMED_CONVERT_FPTR(tmpptr,functions.create);
4064 0 : __PLUMED_FPRINTF(stderr,"%p,",tmpptr);
4065 : __PLUMED_CONVERT_FPTR(tmpptr,functions.cmd);
4066 0 : __PLUMED_FPRINTF(stderr,"%p,",tmpptr);
4067 : __PLUMED_CONVERT_FPTR(tmpptr,functions.finalize);
4068 0 : __PLUMED_FPRINTF(stderr,"%p) +++\n",tmpptr);
4069 : } else {
4070 0 : __PLUMED_FPRINTF(stderr,"+++ plumed_symbol_table (available in PLUMED>=2.5) not found, perhaps kernel is older +++\n");
4071 : }
4072 : }
4073 : /* only searches if they were not found already */
4074 9 : __PLUMED_SEARCH_FUNCTION(plumed_create_pointer,tmpptr,handle,functions.create,"plumedmain_create",debug);
4075 9 : __PLUMED_SEARCH_FUNCTION(plumed_create_pointer,tmpptr,handle,functions.create,"plumed_plumedmain_create",debug);
4076 9 : __PLUMED_SEARCH_FUNCTION(plumed_cmd_pointer,tmpptr,handle,functions.cmd,"plumedmain_cmd",debug);
4077 9 : __PLUMED_SEARCH_FUNCTION(plumed_cmd_pointer,tmpptr,handle,functions.cmd,"plumed_plumedmain_cmd",debug);
4078 9 : __PLUMED_SEARCH_FUNCTION(plumed_finalize_pointer,tmpptr,handle,functions.finalize,"plumedmain_finalize",debug);
4079 9 : __PLUMED_SEARCH_FUNCTION(plumed_finalize_pointer,tmpptr,handle,functions.finalize,"plumed_plumedmain_finalize",debug);
4080 9 : if(functions.create && functions.cmd && functions.finalize) {
4081 9 : if(debug) {
4082 0 : __PLUMED_FPRINTF(stderr,"+++ PLUMED was loaded correctly +++\n");
4083 : }
4084 9 : *f=functions;
4085 9 : if(table) {
4086 9 : *table=table_ptr;
4087 : }
4088 : } else {
4089 0 : if(!functions.create) {
4090 0 : __PLUMED_FPRINTF(stderr,"+++ Pointer to (plumed_)plumedmain_create not found +++\n");
4091 : }
4092 0 : if(!functions.cmd) {
4093 0 : __PLUMED_FPRINTF(stderr,"+++ Pointer to (plumed_)plumedmain_cmd not found +++\n");
4094 : }
4095 0 : if(!functions.finalize) {
4096 0 : __PLUMED_FPRINTF(stderr,"+++ Pointer to (plumed_)plumedmain_finalize not found +++\n");
4097 : }
4098 0 : f->create=__PLUMED_WRAPPER_CXX_NULLPTR;
4099 0 : f->cmd=__PLUMED_WRAPPER_CXX_NULLPTR;
4100 0 : f->finalize=__PLUMED_WRAPPER_CXX_NULLPTR;
4101 0 : if(table) {
4102 0 : *table=__PLUMED_WRAPPER_CXX_NULLPTR;
4103 : }
4104 : }
4105 9 : }
4106 : __PLUMED_WRAPPER_INTERNALS_END
4107 :
4108 : #endif /*}*/
4109 :
4110 :
4111 : #if __PLUMED_WRAPPER_REEXPORT_SYMBOL_TABLE
4112 :
4113 : /*
4114 : Here is the case where plumed_symbol_table is
4115 : visible as extern. We first declare it (together with plumed_symbol_table_init) ...
4116 : */
4117 :
4118 : __PLUMED_WRAPPER_EXTERN_C_BEGIN
4119 : extern
4120 : plumed_symbol_table_type plumed_symbol_table;
4121 : __PLUMED_WRAPPER_EXTERN_C_END
4122 : __PLUMED_WRAPPER_EXTERN_C_BEGIN
4123 : extern
4124 : void plumed_symbol_table_init(void);
4125 : __PLUMED_WRAPPER_EXTERN_C_END
4126 :
4127 : /*
4128 : ... and then make available a function that returns the address
4129 : of the symbol table.
4130 : */
4131 : __PLUMED_WRAPPER_C_BEGIN
4132 680465 : plumed_symbol_table_type* plumed_symbol_table_reexport() {
4133 : /* make sure the table is initialized */
4134 680465 : plumed_symbol_table_init();
4135 696565 : return &plumed_symbol_table;
4136 : }
4137 : __PLUMED_WRAPPER_C_END
4138 :
4139 : #else
4140 :
4141 : /*
4142 : Here is the case where plumed_symbol_table is not
4143 : visible as extern. We thus assume that plumed_symbol_table_reexport is
4144 : available.
4145 : */
4146 :
4147 : __PLUMED_WRAPPER_EXTERN_C_BEGIN
4148 : extern plumed_symbol_table_type* plumed_symbol_table_reexport();
4149 : __PLUMED_WRAPPER_EXTERN_C_END
4150 : #endif
4151 :
4152 :
4153 : /*
4154 : Returns the global pointers, either those available at link time or those
4155 : found in the library loaded at PLUMED_KERNEL env var.
4156 : If plumed_symbol_table_ptr is not NULL, it is used to return a pointer to the symbol table
4157 : (if available).
4158 : Notice that problems can be detected checking if the functions have a NULL ptr.
4159 : On the other hand, the symbol table pointer might be NULL just because the plumed version is <=2.4.
4160 : If handle is not NULL, it is used to return a dlopen handle that could be subsequently dlclosed.
4161 : */
4162 : __PLUMED_WRAPPER_INTERNALS_BEGIN
4163 680835 : void plumed_retrieve_functions(plumed_plumedmain_function_holder* functions, plumed_symbol_table_type** plumed_symbol_table_ptr,void** handle) {
4164 : #if ! __PLUMED_WRAPPER_LINK_RUNTIME
4165 : /*
4166 : Real interface, constructed using the symbol table obtained with plumed_symbol_table_reexport.
4167 : This makes the symbols hardcoded and independent of a mis-set PLUMED_KERNEL variable.
4168 : */
4169 680835 : plumed_symbol_table_type* ptr=plumed_symbol_table_reexport();
4170 698234 : if(plumed_symbol_table_ptr) {
4171 698234 : *plumed_symbol_table_ptr=ptr;
4172 : }
4173 698234 : if(handle) {
4174 698234 : *handle=__PLUMED_WRAPPER_CXX_NULLPTR;
4175 : }
4176 698234 : if(functions) {
4177 698234 : *functions=ptr->functions;
4178 : }
4179 : #elif ! defined(__PLUMED_HAS_DLOPEN)
4180 : /*
4181 : When dlopen is not available, we hard code them to NULL
4182 : */
4183 : __PLUMED_FPRINTF(stderr,"+++ PLUMED has been compiled without dlopen and without a static kernel +++\n");
4184 : plumed_plumedmain_function_holder g= {__PLUMED_WRAPPER_CXX_NULLPTR,__PLUMED_WRAPPER_CXX_NULLPTR,__PLUMED_WRAPPER_CXX_NULLPTR};
4185 : if(plumed_symbol_table_ptr) {
4186 : *plumed_symbol_table_ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
4187 : }
4188 : if(handle) {
4189 : *handle=__PLUMED_WRAPPER_CXX_NULLPTR;
4190 : }
4191 : if(functions) {
4192 : *functions=g;
4193 : }
4194 : #else
4195 : /*
4196 : On the other hand, for runtime binding, we use dlsym to find the relevant functions.
4197 : */
4198 : plumed_plumedmain_function_holder g;
4199 : /* search is done once and only once */
4200 : const char* path;
4201 : void* p;
4202 : char* debug;
4203 : int dlopenmode;
4204 : /* possible value of PLUMED_LOAD_NAMESPACE environment variable */
4205 : char *load_namespace;
4206 : g.create=__PLUMED_WRAPPER_CXX_NULLPTR;
4207 : g.cmd=__PLUMED_WRAPPER_CXX_NULLPTR;
4208 : g.finalize=__PLUMED_WRAPPER_CXX_NULLPTR;
4209 : path=__PLUMED_GETENV("PLUMED_KERNEL");
4210 : p=__PLUMED_WRAPPER_CXX_NULLPTR;
4211 : debug=__PLUMED_GETENV("PLUMED_LOAD_DEBUG");
4212 : dlopenmode=0;
4213 : if(plumed_symbol_table_ptr) {
4214 : *plumed_symbol_table_ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
4215 : }
4216 : if(handle) {
4217 : *handle=__PLUMED_WRAPPER_CXX_NULLPTR;
4218 : }
4219 : #ifdef __PLUMED_DEFAULT_KERNEL
4220 : /*
4221 : This variable allows a default path for the kernel to be hardcoded.
4222 : Can be useful for hardcoding the predefined plumed location
4223 : still allowing the user to override this choice setting PLUMED_KERNEL.
4224 : The path should be chosen at compile time adding e.g.
4225 : -D__PLUMED_DEFAULT_KERNEL=/opt/local/lib/libplumed.dylib
4226 : */
4227 : /* This is required to add quotes */
4228 : #define PLUMED_QUOTE_DIRECT(name) #name
4229 : #define PLUMED_QUOTE(macro) PLUMED_QUOTE_DIRECT(macro)
4230 : if(! (path && (*path) )) {
4231 : path=PLUMED_QUOTE(__PLUMED_DEFAULT_KERNEL);
4232 : }
4233 : #endif
4234 : #if defined(__PLUMED_PROGRAM_NAME) && defined(__PLUMED_SOEXT)
4235 : if(! (path && (*path) )) {
4236 : path="lib" __PLUMED_PROGRAM_NAME "Kernel." __PLUMED_SOEXT;
4237 : }
4238 : #endif
4239 : if(path && (*path)) {
4240 : __PLUMED_FPRINTF(stderr,"+++ Loading the PLUMED kernel runtime +++\n");
4241 : __PLUMED_FPRINTF(stderr,"+++ PLUMED_KERNEL=\"%s\" +++\n",path);
4242 : if(debug) {
4243 : __PLUMED_FPRINTF(stderr,"+++ Loading with mode RTLD_NOW");
4244 : }
4245 : dlopenmode=RTLD_NOW;
4246 : load_namespace = __PLUMED_GETENV("PLUMED_LOAD_NAMESPACE");
4247 : if(load_namespace && !__PLUMED_WRAPPER_STD strcmp(load_namespace,"GLOBAL")) {
4248 : dlopenmode=dlopenmode|RTLD_GLOBAL;
4249 : if(debug) {
4250 : __PLUMED_FPRINTF(stderr,"|RTLD_GLOBAL");
4251 : }
4252 : } else {
4253 : dlopenmode=dlopenmode|RTLD_LOCAL;
4254 : if(debug) {
4255 : __PLUMED_FPRINTF(stderr,"|RTLD_LOCAL");
4256 : }
4257 : }
4258 : #ifdef RTLD_DEEPBIND
4259 : #if __PLUMED_WRAPPER_ENABLE_RTLD_DEEPBIND
4260 : if(!__PLUMED_GETENV("PLUMED_LOAD_NODEEPBIND")) {
4261 : dlopenmode=dlopenmode|RTLD_DEEPBIND;
4262 : if(debug) {
4263 : __PLUMED_FPRINTF(stderr,"|RTLD_DEEPBIND");
4264 : }
4265 : }
4266 : #endif
4267 : #endif
4268 : if(debug) {
4269 : __PLUMED_FPRINTF(stderr," +++\n");
4270 : }
4271 : p=plumed_attempt_dlopen(path,dlopenmode);
4272 : if(p) {
4273 : plumed_search_symbols(p,&g,plumed_symbol_table_ptr);
4274 : }
4275 : }
4276 : if(handle) {
4277 : *handle=p;
4278 : }
4279 : if(functions) {
4280 : *functions=g;
4281 : }
4282 : #endif
4283 698234 : }
4284 : __PLUMED_WRAPPER_INTERNALS_END
4285 :
4286 : /**
4287 : Implementation.
4288 : Small object used to store pointers directly into the plumed object defined in Plumed.h.
4289 : This allows avoiding the extra function call to plumed_retrieve_functions at every cmd,
4290 : at the cost of an extra indirection.
4291 : */
4292 : typedef struct {
4293 : /* allows errors with pointers to be found when debugging */
4294 : char magic[6];
4295 : /* reference count. this is only used with PLUMED<=2.8. Later versions have an internal thread-safe reference counter. */
4296 : int refcount;
4297 : /* handler to dlopened library. NULL if there was no library opened */
4298 : void* dlhandle;
4299 : /* non zero if, upon destruction, the library should be dlclosed */
4300 : int dlclose;
4301 : /* 1 if path to kernel was taken from PLUMED_KERNEL var, 0 otherwise */
4302 : int used_plumed_kernel;
4303 : /* function pointers */
4304 : plumed_plumedmain_function_holder functions;
4305 : /* pointer to the symbol table. NULL if kernel <=2.4 */
4306 : plumed_symbol_table_type* table;
4307 : /* pointer to plumed object */
4308 : void* p;
4309 : } plumed_implementation;
4310 :
4311 : __PLUMED_WRAPPER_INTERNALS_BEGIN
4312 698989 : plumed_implementation* plumed_malloc_pimpl() {
4313 : plumed_implementation* pimpl;
4314 : /* allocate space for implementation object. this is free-ed in plumed_finalize(). */
4315 698988 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, plumed_malloc(sizeof(plumed_implementation)));
4316 715617 : if(!pimpl) {
4317 0 : __PLUMED_FPRINTF(stderr,"+++ Allocation error +++\n");
4318 0 : __PLUMED_WRAPPER_STD abort();
4319 : }
4320 : /* cppcheck-suppress nullPointerRedundantCheck */
4321 715617 : __PLUMED_WRAPPER_STD memcpy(pimpl->magic,"pLuMEd",6);
4322 : /* cppcheck-suppress nullPointerRedundantCheck */
4323 715617 : pimpl->refcount=1;
4324 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4325 : /* cppcheck-suppress nullPointerRedundantCheck */
4326 : __PLUMED_FPRINTF(stderr,"refcount: new at %p\n",__PLUMED_WRAPPER_STATIC_CAST(void*,pimpl));
4327 : #endif
4328 : /* cppcheck-suppress nullPointerRedundantCheck */
4329 715617 : pimpl->dlhandle=__PLUMED_WRAPPER_CXX_NULLPTR;
4330 : /* cppcheck-suppress nullPointerRedundantCheck */
4331 715617 : pimpl->dlclose=0;
4332 : /* cppcheck-suppress nullPointerRedundantCheck */
4333 715617 : pimpl->used_plumed_kernel=0;
4334 : /* cppcheck-suppress nullPointerRedundantCheck */
4335 715617 : pimpl->functions.create=__PLUMED_WRAPPER_CXX_NULLPTR;
4336 : /* cppcheck-suppress nullPointerRedundantCheck */
4337 715617 : pimpl->functions.cmd=__PLUMED_WRAPPER_CXX_NULLPTR;
4338 : /* cppcheck-suppress nullPointerRedundantCheck */
4339 715617 : pimpl->functions.finalize=__PLUMED_WRAPPER_CXX_NULLPTR;
4340 : /* cppcheck-suppress nullPointerRedundantCheck */
4341 715617 : pimpl->table=__PLUMED_WRAPPER_CXX_NULLPTR;
4342 : /* cppcheck-suppress nullPointerRedundantCheck */
4343 715617 : pimpl->p=__PLUMED_WRAPPER_CXX_NULLPTR;
4344 715617 : return pimpl;
4345 : }
4346 : __PLUMED_WRAPPER_INTERNALS_END
4347 :
4348 : #ifndef NDEBUG
4349 :
4350 : __PLUMED_WRAPPER_INTERNALS_BEGIN
4351 : int plumed_check_pimpl(plumed_implementation*pimpl) {
4352 : if(!pimpl) {
4353 : return 0;
4354 : }
4355 : if(__PLUMED_WRAPPER_STD memcmp(pimpl->magic,"pLuMEd",6)) {
4356 : return 0;
4357 : }
4358 : return 1;
4359 : }
4360 : __PLUMED_WRAPPER_INTERNALS_END
4361 : #endif
4362 :
4363 : /* C wrappers: */
4364 :
4365 : __PLUMED_WRAPPER_C_BEGIN
4366 711955 : plumed plumed_create(void) {
4367 : /* returned object */
4368 : plumed p;
4369 : /* pointer to implementation */
4370 : plumed_implementation* pimpl;
4371 : /* possible value of PLUMED_LOAD_DLCLOSE environment variable */
4372 : char *load_dlclose;
4373 : /* allocate space for implementation object. this is free-ed in plumed_finalize(). */
4374 711955 : pimpl=plumed_malloc_pimpl();
4375 : /* store pointers in pimpl */
4376 713231 : plumed_retrieve_functions(&pimpl->functions,&pimpl->table,&pimpl->dlhandle);
4377 : #if __PLUMED_WRAPPER_LINK_RUNTIME
4378 : /* note if PLUMED_KERNEL variable was used */
4379 : pimpl->used_plumed_kernel=1;
4380 : #endif
4381 : /* note if handle should not be dlclosed */
4382 736404 : pimpl->dlclose=1;
4383 736404 : load_dlclose = __PLUMED_GETENV("PLUMED_LOAD_DLCLOSE");
4384 775906 : if(load_dlclose && !__PLUMED_WRAPPER_STD strcmp(load_dlclose,"no")) {
4385 0 : pimpl->dlclose=0;
4386 : }
4387 : /* in case of failure, return */
4388 : /* the resulting object should be plumed_finalized, though you cannot use plumed_cmd */
4389 775906 : if(!pimpl->functions.create) {
4390 : /* store pimpl in returned object */
4391 : p.p=pimpl;
4392 0 : return p;
4393 : }
4394 : assert(pimpl->functions.cmd);
4395 : assert(pimpl->functions.finalize);
4396 : /* obtain object */
4397 775906 : pimpl->p=(*(pimpl->functions.create))();
4398 : /* notice: we do not assert pimpl->p since in principle it might be nullptr */
4399 : /* user might identify this using plumed_valid() */
4400 : /* store pimpl in returned object */
4401 : p.p=pimpl;
4402 787798 : return p;
4403 : }
4404 : __PLUMED_WRAPPER_C_END
4405 :
4406 : __PLUMED_WRAPPER_C_BEGIN
4407 9 : plumed plumed_create_dlopen(const char*path) {
4408 : int dlopenmode;
4409 : /* plumed_create_dlopen always uses RTLD_LOCAL and, when possible, RTLD_DEEPBIND to allow multiple versions */
4410 : #ifdef __PLUMED_HAS_DLOPEN
4411 : dlopenmode=RTLD_NOW|RTLD_LOCAL;
4412 : #ifdef RTLD_DEEPBIND
4413 : #if __PLUMED_WRAPPER_ENABLE_RTLD_DEEPBIND
4414 9 : if(!__PLUMED_GETENV("PLUMED_LOAD_NODEEPBIND")) {
4415 : dlopenmode=dlopenmode|RTLD_DEEPBIND;
4416 : }
4417 : #endif
4418 : #endif
4419 : #else
4420 : dlopenmode=0;
4421 : #endif
4422 9 : return plumed_create_dlopen2(path,dlopenmode);
4423 : }
4424 : __PLUMED_WRAPPER_C_END
4425 :
4426 : __PLUMED_WRAPPER_C_BEGIN
4427 9 : plumed plumed_create_dlsym(void* dlhandle) {
4428 : /* returned object */
4429 : plumed p;
4430 : /* pointer to implementation */
4431 : plumed_implementation* pimpl;
4432 : /* allocate space for implementation object. this is free-ed in plumed_finalize(). */
4433 9 : pimpl=plumed_malloc_pimpl();
4434 : #ifdef __PLUMED_HAS_DLOPEN
4435 9 : pimpl->dlhandle=dlhandle;
4436 9 : plumed_search_symbols(pimpl->dlhandle,&pimpl->functions,&pimpl->table);
4437 : #endif
4438 9 : if(!pimpl->functions.create) {
4439 : p.p=pimpl;
4440 0 : return p;
4441 : }
4442 : assert(pimpl->functions.cmd);
4443 : assert(pimpl->functions.finalize);
4444 : /* obtain object */
4445 9 : pimpl->p=(*(pimpl->functions.create))();
4446 : /* notice: we do not assert pimpl->p since in principle it might be nullptr */
4447 : /* user might identify this using plumed_valid() */
4448 : /* store pimpl in returned object */
4449 : p.p=pimpl;
4450 9 : return p;
4451 : }
4452 : __PLUMED_WRAPPER_C_END
4453 :
4454 : __PLUMED_WRAPPER_C_BEGIN
4455 9 : plumed plumed_create_dlopen2(const char*path,int mode) {
4456 : #ifdef __PLUMED_HAS_DLOPEN
4457 : /* returned object */
4458 : plumed p;
4459 : /* pointer to implementation */
4460 : plumed_implementation* pimpl;
4461 : /* handler */
4462 : void* dlhandle;
4463 : dlhandle=__PLUMED_WRAPPER_CXX_NULLPTR;
4464 9 : if(path) {
4465 9 : dlhandle=plumed_attempt_dlopen(path,mode);
4466 : }
4467 : /* a NULL handle implies the file could not be loaded */
4468 9 : if(dlhandle) {
4469 9 : p=plumed_create_dlsym(dlhandle);
4470 : /* obtain pimpl */
4471 9 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4472 : /* make sure the handler is closed when plumed is finalized */
4473 9 : pimpl->dlclose=1;
4474 9 : return p;
4475 : }
4476 : #else
4477 : (void) path;
4478 : (void) mode;
4479 : #endif
4480 0 : return plumed_create_invalid();
4481 : }
4482 : __PLUMED_WRAPPER_C_END
4483 :
4484 : __PLUMED_WRAPPER_C_BEGIN
4485 7805113 : plumed plumed_create_reference(plumed p) {
4486 : plumed_implementation* pimpl;
4487 : /* obtain pimpl */
4488 7805113 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4489 : assert(plumed_check_pimpl(pimpl));
4490 : /* increase reference count */
4491 : /* with PLUMED > 2.8, we can use an internal reference counter which is thread safe */
4492 7805113 : if(pimpl->p && pimpl->table && pimpl->table->version>3) {
4493 7743037 : pimpl->table->create_reference(pimpl->p);
4494 : } else {
4495 62076 : pimpl->refcount++;
4496 : }
4497 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4498 : __PLUMED_FPRINTF(stderr,"refcount: increase at %p\n",__PLUMED_WRAPPER_STATIC_CAST(void*,pimpl));
4499 : #endif
4500 7553218 : return p;
4501 : }
4502 : __PLUMED_WRAPPER_C_END
4503 :
4504 : __PLUMED_WRAPPER_C_BEGIN
4505 2 : plumed plumed_create_reference_v(void*v) {
4506 2 : return plumed_create_reference(plumed_v2c(v));
4507 : }
4508 : __PLUMED_WRAPPER_C_END
4509 :
4510 : __PLUMED_WRAPPER_C_BEGIN
4511 8 : plumed plumed_create_reference_f(const char*f) {
4512 8 : return plumed_create_reference(plumed_f2c(f));
4513 : }
4514 : __PLUMED_WRAPPER_C_END
4515 :
4516 : __PLUMED_WRAPPER_C_BEGIN
4517 2 : plumed plumed_create_invalid() {
4518 : plumed p;
4519 : plumed_implementation* pimpl;
4520 2 : pimpl=plumed_malloc_pimpl();
4521 : p.p=pimpl;
4522 2 : return p;
4523 : }
4524 : __PLUMED_WRAPPER_C_END
4525 :
4526 : __PLUMED_WRAPPER_C_BEGIN
4527 357 : void plumed_cmd(plumed p,const char*key,const void*val) {
4528 : plumed_implementation* pimpl;
4529 : /* obtain pimpl */
4530 357 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4531 : assert(plumed_check_pimpl(pimpl));
4532 357 : if(!pimpl->p) {
4533 0 : __PLUMED_FPRINTF(stderr,"+++ ERROR: You are trying to use an invalid plumed object. +++\n");
4534 0 : if(pimpl->used_plumed_kernel) {
4535 0 : __PLUMED_FPRINTF(stderr,"+++ Check your PLUMED_KERNEL environment variable. +++\n");
4536 : }
4537 0 : __PLUMED_WRAPPER_STD abort();
4538 : }
4539 : assert(pimpl->functions.create);
4540 : assert(pimpl->functions.cmd);
4541 : assert(pimpl->functions.finalize);
4542 : /* execute */
4543 357 : (*(pimpl->functions.cmd))(pimpl->p,key,val);
4544 357 : }
4545 : __PLUMED_WRAPPER_C_END
4546 :
4547 : __PLUMED_WRAPPER_C_BEGIN
4548 19738 : void plumed_cmd_safe_nothrow(plumed p,const char*key,plumed_safeptr safe,plumed_nothrow_handler nothrow) {
4549 : plumed_implementation* pimpl;
4550 : /* This is to allow caller to use a null handler to imply that handling is not done */
4551 19738 : if(!nothrow.handler) {
4552 37 : plumed_cmd_safe(p,key,safe);
4553 37 : return;
4554 : }
4555 : /* obtain pimpl */
4556 19701 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4557 : assert(plumed_check_pimpl(pimpl));
4558 19701 : if(!pimpl->p) {
4559 0 : if(pimpl->used_plumed_kernel) {
4560 0 : nothrow.handler(nothrow.ptr,1,"You are trying to use plumed, but it is not available.\nCheck your PLUMED_KERNEL environment variable.",__PLUMED_WRAPPER_CXX_NULLPTR);
4561 : } else {
4562 0 : nothrow.handler(nothrow.ptr,1,"You are trying to use plumed, but it is not available.",__PLUMED_WRAPPER_CXX_NULLPTR);
4563 : }
4564 0 : return;
4565 : }
4566 : assert(pimpl->functions.create);
4567 : assert(pimpl->functions.cmd);
4568 : assert(pimpl->functions.finalize);
4569 : /* execute */
4570 19701 : if(pimpl->table && pimpl->table->version>2) {
4571 19701 : (*(pimpl->table->cmd_safe_nothrow))(pimpl->p,key,safe,nothrow);
4572 0 : } else if(pimpl->table && pimpl->table->version>1) {
4573 0 : (*(pimpl->table->cmd_nothrow))(pimpl->p,key,safe.ptr,nothrow);
4574 : } else {
4575 0 : (*(pimpl->functions.cmd))(pimpl->p,key,safe.ptr);
4576 : }
4577 : }
4578 : __PLUMED_WRAPPER_C_END
4579 :
4580 : __PLUMED_WRAPPER_C_BEGIN
4581 0 : void plumed_cmd_nothrow(plumed p,const char*key,const void*val,plumed_nothrow_handler nothrow) {
4582 : plumed_safeptr safe;
4583 0 : safe.ptr=val;
4584 0 : safe.flags=0;
4585 0 : safe.nelem=0;
4586 0 : safe.shape=__PLUMED_WRAPPER_CXX_NULLPTR;
4587 0 : safe.opt=__PLUMED_WRAPPER_CXX_NULLPTR;
4588 0 : plumed_cmd_safe_nothrow(p,key,safe,nothrow);
4589 0 : }
4590 : __PLUMED_WRAPPER_C_END
4591 :
4592 : __PLUMED_WRAPPER_C_BEGIN
4593 95 : void plumed_cmd_safe(plumed p,const char*key,plumed_safeptr safe) {
4594 : plumed_implementation* pimpl;
4595 : /* obtain pimpl */
4596 95 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4597 : assert(plumed_check_pimpl(pimpl));
4598 95 : if(!pimpl->p) {
4599 0 : __PLUMED_FPRINTF(stderr,"+++ ERROR: You are trying to use an invalid plumed object. +++\n");
4600 0 : if(pimpl->used_plumed_kernel) {
4601 0 : __PLUMED_FPRINTF(stderr,"+++ Check your PLUMED_KERNEL environment variable. +++\n");
4602 : }
4603 0 : __PLUMED_WRAPPER_STD abort();
4604 : }
4605 : assert(pimpl->functions.create);
4606 : assert(pimpl->functions.cmd);
4607 : assert(pimpl->functions.finalize);
4608 : /* execute */
4609 95 : if(pimpl->table && pimpl->table->version>2) {
4610 95 : (*(pimpl->table->cmd_safe))(pimpl->p,key,safe);
4611 : } else {
4612 0 : (*(pimpl->functions.cmd))(pimpl->p,key,safe.ptr);
4613 : }
4614 95 : }
4615 : __PLUMED_WRAPPER_C_END
4616 :
4617 :
4618 : __PLUMED_WRAPPER_C_BEGIN
4619 8392918 : void plumed_finalize(plumed p) {
4620 : plumed_implementation* pimpl;
4621 : /* obtain pimpl */
4622 8392918 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4623 : assert(plumed_check_pimpl(pimpl));
4624 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4625 : __PLUMED_FPRINTF(stderr,"refcount: decrease at %p\n",__PLUMED_WRAPPER_STATIC_CAST(void*,pimpl));
4626 : #endif
4627 : /* with PLUMED > 2.8, we can use an internal reference counter which is thread safe */
4628 8392918 : if(pimpl->p && pimpl->table && pimpl->table->version>3) {
4629 8363156 : if(pimpl->table->delete_reference(pimpl->p)>0) {
4630 : return;
4631 : }
4632 : } else {
4633 29762 : if(--pimpl->refcount>0) {
4634 : return;
4635 : }
4636 : }
4637 : /* to allow finalizing an invalid plumed object, we only call
4638 : finalize if the object is valid */
4639 788969 : if(pimpl->p) {
4640 : assert(pimpl->functions.create);
4641 : assert(pimpl->functions.cmd);
4642 : assert(pimpl->functions.finalize);
4643 : /* finalize */
4644 788967 : (*(pimpl->functions.finalize))(pimpl->p);
4645 : }
4646 : #ifdef __PLUMED_HAS_DLOPEN
4647 : /* dlclose library */
4648 745554 : if(pimpl->dlhandle && pimpl->dlclose) {
4649 9 : if(__PLUMED_GETENV("PLUMED_LOAD_DEBUG")) {
4650 0 : __PLUMED_FPRINTF(stderr,"+++ Unloading library\n");
4651 : }
4652 9 : dlclose(pimpl->dlhandle);
4653 : }
4654 : #endif
4655 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4656 : __PLUMED_FPRINTF(stderr,"refcount: delete at %p\n",__PLUMED_WRAPPER_STATIC_CAST(void*,pimpl));
4657 : #endif
4658 : /* free pimpl space */
4659 745553 : plumed_free(pimpl);
4660 : }
4661 : __PLUMED_WRAPPER_C_END
4662 :
4663 : __PLUMED_WRAPPER_C_BEGIN
4664 23 : int plumed_valid(plumed p) {
4665 : plumed_implementation* pimpl;
4666 : /* obtain pimpl */
4667 23 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4668 : assert(plumed_check_pimpl(pimpl));
4669 24 : if(pimpl->p) {
4670 : return 1;
4671 : } else {
4672 2 : return 0;
4673 : }
4674 : }
4675 : __PLUMED_WRAPPER_C_END
4676 :
4677 : __PLUMED_WRAPPER_C_BEGIN
4678 42 : int plumed_use_count(plumed p) {
4679 : plumed_implementation* pimpl;
4680 : /* obtain pimpl */
4681 42 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4682 : assert(plumed_check_pimpl(pimpl));
4683 : /* with PLUMED > 2.8, we can use an internal reference counter which is thread safe */
4684 42 : if(pimpl->p && pimpl->table && pimpl->table->version>3) {
4685 42 : return pimpl->table->use_count(pimpl->p);
4686 : } else {
4687 0 : return pimpl->refcount;
4688 : }
4689 : }
4690 : __PLUMED_WRAPPER_C_END
4691 :
4692 : __PLUMED_WRAPPER_C_BEGIN
4693 9 : int plumed_installed(void) {
4694 : plumed p;
4695 : int result;
4696 9 : p=plumed_create();
4697 9 : result=plumed_valid(p);
4698 9 : plumed_finalize(p);
4699 9 : return result;
4700 : }
4701 : __PLUMED_WRAPPER_C_END
4702 :
4703 : __PLUMED_WRAPPER_C_BEGIN
4704 696503 : void* plumed_malloc(__PLUMED_WRAPPER_STD size_t size) {
4705 : void* ptr;
4706 696504 : ptr=__PLUMED_WRAPPER_STD malloc(size);
4707 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4708 : if(ptr) {
4709 : fprintf(stderr,"plumed_malloc: %p\n",ptr);
4710 : }
4711 : #endif
4712 696503 : return ptr;
4713 : }
4714 : __PLUMED_WRAPPER_C_END
4715 :
4716 : __PLUMED_WRAPPER_C_BEGIN
4717 719077 : void plumed_free(void* ptr) {
4718 719078 : __PLUMED_WRAPPER_STD free(ptr);
4719 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4720 : fprintf(stderr,"plumed_free: %p\n",ptr);
4721 : #endif
4722 719078 : }
4723 : __PLUMED_WRAPPER_C_END
4724 :
4725 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
4726 :
4727 : __PLUMED_WRAPPER_EXTERN_C_BEGIN
4728 :
4729 : /* we declare a Plumed_g_main object here, in such a way that it is always available */
4730 :
4731 : static plumed plumed_gmain= {__PLUMED_WRAPPER_CXX_NULLPTR};
4732 :
4733 589 : plumed plumed_global(void) {
4734 589 : return plumed_gmain;
4735 : }
4736 :
4737 61 : void plumed_gcreate(void) {
4738 : /* should be created once */
4739 : assert(plumed_gmain.p==__PLUMED_WRAPPER_CXX_NULLPTR);
4740 61 : plumed_gmain=plumed_create();
4741 61 : }
4742 :
4743 78 : void plumed_gcmd(const char*key,const void*val) {
4744 78 : plumed_cmd(plumed_gmain,key,val);
4745 78 : }
4746 :
4747 : /* cppcheck-suppress passedByValue */
4748 0 : void plumed_gcmd_safe(const char*key,plumed_safeptr safe) {
4749 0 : plumed_cmd_safe(plumed_gmain,key,safe);
4750 0 : }
4751 :
4752 61 : void plumed_gfinalize(void) {
4753 61 : plumed_finalize(plumed_gmain);
4754 61 : plumed_gmain.p=__PLUMED_WRAPPER_CXX_NULLPTR;
4755 61 : }
4756 :
4757 24 : int plumed_ginitialized(void) {
4758 24 : if(plumed_gmain.p) {
4759 : return 1;
4760 : } else {
4761 16 : return 0;
4762 : }
4763 : }
4764 :
4765 8 : int plumed_gvalid() {
4766 : assert(plumed_gmain.p);
4767 8 : return plumed_valid(plumed_gmain);
4768 : }
4769 :
4770 : __PLUMED_WRAPPER_EXTERN_C_END
4771 :
4772 : #endif /*}*/
4773 :
4774 : __PLUMED_WRAPPER_C_BEGIN
4775 56 : void plumed_c2f(plumed p,char*c) {
4776 : unsigned i;
4777 : unsigned char* cc;
4778 : /*
4779 : Convert the address stored in p.p into a proper FORTRAN string
4780 : made of only ASCII characters. For this to work, the two following
4781 : assertions should be satisfied:
4782 : */
4783 : assert(CHAR_BIT<=12);
4784 : assert(sizeof(p.p)<=16);
4785 :
4786 : assert(c);
4787 : cc=__PLUMED_WRAPPER_REINTERPRET_CAST(unsigned char*,&p.p);
4788 504 : for(i=0; i<sizeof(p.p); i++) {
4789 : /*
4790 : characters will range between '0' (ASCII 48) and 'o' (ASCII 111=48+63)
4791 : */
4792 448 : c[2*i]=cc[i]/64+48;
4793 448 : c[2*i+1]=cc[i]%64+48;
4794 : }
4795 504 : for(; i<16; i++) {
4796 448 : c[2*i]=' ';
4797 448 : c[2*i+1]=' ';
4798 : }
4799 56 : }
4800 : __PLUMED_WRAPPER_C_END
4801 :
4802 : __PLUMED_WRAPPER_C_BEGIN
4803 373 : plumed plumed_f2c(const char*c) {
4804 : plumed p;
4805 : unsigned i;
4806 : unsigned char* cc;
4807 :
4808 : assert(CHAR_BIT<=12);
4809 : assert(sizeof(p.p)<=16);
4810 :
4811 : assert(c);
4812 :
4813 : /*
4814 : needed to avoid cppcheck warning on uninitialized p
4815 : */
4816 373 : p.p=__PLUMED_WRAPPER_CXX_NULLPTR;
4817 : cc=__PLUMED_WRAPPER_REINTERPRET_CAST(unsigned char*,&p.p);
4818 3357 : for(i=0; i<sizeof(p.p); i++) {
4819 : assert(c[2*i]>=48 && c[2*i]<48+64);
4820 : assert(c[2*i+1]>=48 && c[2*i+1]<48+64);
4821 : /*
4822 : perform the reversed transform
4823 : */
4824 2984 : cc[i]=(c[2*i]-48)*64 + (c[2*i+1]-48);
4825 : }
4826 3357 : for(; i<16; i++) {
4827 : assert(c[2*i]==' ');
4828 : assert(c[2*i+1]==' ');
4829 : }
4830 373 : return p;
4831 : }
4832 : __PLUMED_WRAPPER_C_END
4833 :
4834 : __PLUMED_WRAPPER_C_BEGIN
4835 2 : void* plumed_c2v(plumed p) {
4836 : assert(plumed_check_pimpl(__PLUMED_WRAPPER_REINTERPRET_CAST(plumed_implementation*,p.p)));
4837 2 : return p.p;
4838 : }
4839 : __PLUMED_WRAPPER_C_END
4840 :
4841 : __PLUMED_WRAPPER_C_BEGIN
4842 2 : plumed plumed_v2c(void* v) {
4843 : assert(plumed_check_pimpl(__PLUMED_WRAPPER_REINTERPRET_CAST(plumed_implementation*,v)));
4844 : plumed p;
4845 : p.p=v;
4846 2 : return p;
4847 : }
4848 : __PLUMED_WRAPPER_C_END
4849 :
4850 : #if __PLUMED_WRAPPER_FORTRAN /*{*/
4851 :
4852 : /*
4853 : Fortran wrappers
4854 : These are just like the global C wrappers. They are
4855 : just defined here and not declared since they
4856 : should not be used from c/c++ anyway.
4857 :
4858 : We use a macro that does the following:
4859 : - declare a static function named NAME_static
4860 : - declare a number of functions named NAME_ etc, with all possible
4861 : fortran mangling schemes (zero, one, or two underscores, lower and upper case)
4862 : - define the NAME_static function.
4863 :
4864 : The static function is used basically as an inline function in a C-compatible manner.
4865 : */
4866 :
4867 : #define __PLUMED_IMPLEMENT_FORTRAN(lower,upper,arg1,arg2) \
4868 : static void lower ## _static arg1; \
4869 : extern void lower arg1 {lower ## _static arg2;} \
4870 : extern void lower ##_ arg1 {lower ## _static arg2;} \
4871 : extern void lower ##__ arg1 {lower ## _static arg2;} \
4872 : extern void upper arg1 {lower ## _static arg2;} \
4873 : extern void upper ##_ arg1 {lower ## _static arg2;} \
4874 : extern void upper ##__ arg1 {lower ## _static arg2;} \
4875 : static void lower ## _static arg1
4876 :
4877 : /* FORTRAN wrappers would only make sense as extern "C" */
4878 :
4879 : __PLUMED_WRAPPER_EXTERN_C_BEGIN
4880 :
4881 36 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create,PLUMED_F_CREATE,(char*c),(c)) {
4882 18 : plumed_c2f(plumed_create(),c);
4883 18 : }
4884 :
4885 12 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create_dlopen,PLUMED_F_CREATE_DLOPEN,(char*path,char*c),(path,c)) {
4886 6 : plumed_c2f(plumed_create_dlopen(path),c);
4887 6 : }
4888 :
4889 12 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create_reference,PLUMED_F_CREATE_REFERENCE,(char* r,char*c),(r,c)) {
4890 6 : plumed_c2f(plumed_create_reference_f(r),c);
4891 6 : }
4892 :
4893 0 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create_invalid,PLUMED_F_CREATE_INVALID,(char* c),(c)) {
4894 0 : plumed_c2f(plumed_create_invalid(),c);
4895 0 : }
4896 :
4897 558 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_cmd,PLUMED_F_CMD,(char*c,char*key,void*val),(c,key,val)) {
4898 279 : plumed_cmd(plumed_f2c(c),key,val);
4899 279 : }
4900 :
4901 60 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_finalize,PLUMED_F_FINALIZE,(char*c),(c)) {
4902 30 : plumed_finalize(plumed_f2c(c));
4903 30 : }
4904 :
4905 12 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_installed,PLUMED_F_INSTALLED,(int*i),(i)) {
4906 : assert(i);
4907 6 : *i=plumed_installed();
4908 6 : }
4909 :
4910 : /* New in PLUMED 2.5 */
4911 0 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_valid,PLUMED_F_VALID,(char*c,int*i),(c,i)) {
4912 : assert(i);
4913 0 : *i=plumed_valid(plumed_f2c(c));
4914 0 : }
4915 :
4916 36 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_use_count,PLUMED_F_USE_COUNT,(char*c,int*i),(c,i)) {
4917 : assert(i);
4918 18 : *i=plumed_use_count(plumed_f2c(c));
4919 18 : }
4920 :
4921 : /* New in PLUMED 2.8 */
4922 :
4923 : /* note: flags & (~0x1ffffff) removes bits that are set here (code and size) */
4924 :
4925 : #define __PLUMED_IMPLEMENT_F_SAFEPTR_INNER(type,type_,size,code,suffix) \
4926 : plumed_safeptr plumed_f_safeptr_ ## type_ ## suffix(void*val,__PLUMED_WRAPPER_STD size_t nelem,__PLUMED_WRAPPER_STD size_t*shape,__PLUMED_WRAPPER_STD size_t flags,void*opt) {\
4927 : plumed_safeptr safe; \
4928 : safe.ptr=val; \
4929 : safe.nelem=nelem; \
4930 : safe.shape=shape; \
4931 : safe.flags= (flags & (~0x1ffffffu)) + 0x10000*code + size; \
4932 : safe.opt=opt; \
4933 : return safe; \
4934 : }
4935 :
4936 : #define __PLUMED_IMPLEMENT_F_SAFEPTR(type,type_,size,code) \
4937 : __PLUMED_IMPLEMENT_F_SAFEPTR_INNER(type,type_,size,code,) \
4938 : __PLUMED_IMPLEMENT_F_SAFEPTR_INNER(type,type_,size,code,_scalar)
4939 :
4940 : #define __PLUMED_IMPLEMENT_F_SAFEPTR_EMPTY(type,type_,code) \
4941 : __PLUMED_IMPLEMENT_F_SAFEPTR(type,type_,0,code)
4942 :
4943 : #define __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(type,type_,code) \
4944 : __PLUMED_IMPLEMENT_F_SAFEPTR(type,type_,sizeof(type),code)
4945 :
4946 24 : __PLUMED_IMPLEMENT_F_SAFEPTR_EMPTY(void,ptr,0)
4947 1 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(float,float,4)
4948 19 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(double,double,4)
4949 0 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(long double,long_double,4)
4950 19 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(int,int,3)
4951 0 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(short,short,3)
4952 0 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(long,long,3)
4953 20 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(char,char,3)
4954 :
4955 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
4956 :
4957 48 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_global,PLUMED_F_GLOBAL,(char*c),(c)) {
4958 24 : plumed_c2f(plumed_gmain,c);
4959 24 : }
4960 :
4961 36 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_ginitialized,PLUMED_F_GINITIALIZED,(int*i),(i)) {
4962 : assert(i);
4963 18 : *i=plumed_ginitialized();
4964 18 : }
4965 :
4966 28 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_gcreate,PLUMED_F_GCREATE,(void),()) {
4967 14 : plumed_gcreate();
4968 14 : }
4969 :
4970 156 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_gcmd,PLUMED_F_GCMD,(char*key,void*val),(key,val)) {
4971 78 : plumed_gcmd(key,val);
4972 78 : }
4973 :
4974 28 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_gfinalize,PLUMED_F_GFINALIZE,(void),()) {
4975 14 : plumed_gfinalize();
4976 14 : }
4977 :
4978 : /* New in PLUMED 2.5 */
4979 12 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_gvalid,PLUMED_F_GVALID,(int*i),(i)) {
4980 : assert(i);
4981 6 : *i=plumed_gvalid();
4982 6 : }
4983 :
4984 : #endif /*}*/
4985 :
4986 : __PLUMED_WRAPPER_EXTERN_C_END
4987 :
4988 : #endif /*}*/
4989 :
4990 : #endif /*}*/
4991 :
4992 : #endif /*}*/
4993 :
4994 : /* END OF DEFINITIONS */
4995 :
4996 : /* reset variable to allow it to be redefined upon re-inclusion */
4997 :
4998 : #undef __PLUMED_WRAPPER_IMPLEMENTATION_
4999 :
5000 : /* this macro is set in declarations */
5001 : #ifdef __PLUMED_WRAPPER_REDEFINE_CMD
5002 : #if defined(plumed_cmd)
5003 : #undef plumed_cmd
5004 : #endif
5005 : #define plumed_cmd __PLUMED_WRAPPER_REDEFINE_CMD
5006 : #endif
5007 :
5008 : /* this macro is set in declarations */
5009 : #ifdef __PLUMED_WRAPPER_REDEFINE_GCMD
5010 : #if defined(plumed_gcmd)
5011 : #undef plumed_gcmd
5012 : #endif
5013 : #define plumed_gcmd __PLUMED_WRAPPER_REDEFINE_GCMD
5014 : #endif
5015 :
5016 : /* this macro is set in declarations */
5017 : #ifdef __PLUMED_WRAPPER_REDEFINE_ERROR_RETHROW
5018 : #if defined(plumed_error_rethrow)
5019 : #undef plumed_error_rethrow
5020 : #endif
5021 : #define plumed_error_rethrow __PLUMED_WRAPPER_REDEFINE_ERROR_RETHROW
5022 : #endif
|