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 16363 : error->code=0;
919 16363 : error->error_code=0;
920 16363 : error->error_category=0;
921 16363 : error->path1.numbytes=0;
922 16363 : error->path1.ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
923 16363 : error->path2.numbytes=0;
924 16363 : error->path2.ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
925 16363 : error->what=__PLUMED_WRAPPER_CXX_NULLPTR;
926 16363 : error->what_buffer=__PLUMED_WRAPPER_CXX_NULLPTR;
927 16363 : 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) return;
934 0 : if(error.nested) {
935 0 : plumed_error_finalize(*error.nested);
936 0 : plumed_free(error.nested);
937 : }
938 0 : if(error.path1.ptr) {
939 0 : plumed_free(error.path1.ptr);
940 : }
941 0 : if(error.path2.ptr) {
942 0 : plumed_free(error.path2.ptr);
943 : }
944 0 : if(error.what_buffer) {
945 0 : plumed_free(error.what_buffer);
946 : }
947 : }
948 :
949 : /** Access message - more robust than directly accessing what ptr, for future extensibility */
950 : /* cppcheck-suppress passedByValue */
951 : __PLUMED_WRAPPER_STATIC_INLINE const char* plumed_error_what(plumed_error error) __PLUMED_WRAPPER_CXX_NOEXCEPT {
952 : return error.what;
953 : }
954 :
955 : /** Set error to bad_alloc (for internal usage).
956 : At variance with plumed_error_init, it also finalizes the error, possibly
957 : deallocating any buffer.
958 : */
959 0 : __PLUMED_WRAPPER_STATIC_INLINE void plumed_error_set_bad_alloc(plumed_error*error) {
960 : assert(error);
961 0 : plumed_error_finalize(*error);
962 : plumed_error_init(error);
963 0 : error->what="[msg erased due to allocation failure]";
964 0 : error->code=11400;
965 0 : }
966 :
967 : /** Recursive merge (for internal usage) */
968 : __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 {
969 : if(error->nested) plumed_error_recursive_merge(error->nested,buffer,join,len);
970 : __PLUMED_WRAPPER_STD strncat(buffer,plumed_error_what(*error),*len);
971 : *len -= __PLUMED_WRAPPER_STD strlen(plumed_error_what(*error));
972 : __PLUMED_WRAPPER_STD strncat(buffer,join,*len);
973 : *len -= __PLUMED_WRAPPER_STD strlen(join);
974 : }
975 :
976 : /** Merge with nested exceptions */
977 : __PLUMED_WRAPPER_STATIC_INLINE void plumed_error_merge_with_nested(plumed_error* error) __PLUMED_WRAPPER_CXX_NOEXCEPT {
978 : __PLUMED_WRAPPER_STD size_t len;
979 : __PLUMED_WRAPPER_STD size_t len_join;
980 : /* The is temporarily holding the new message */
981 : char* new_buffer;
982 : /* This is the string used to concatenate messages */
983 : const char* join="\n\nThe above exception was the direct cause of the following exception:\n";
984 : /* This is used to iterate over the linked list of nested exceptions */
985 : plumed_error*e;
986 :
987 : /* If exception is not nested, nothing to do */
988 : if(!error->nested) return;
989 :
990 : /* Accumulate the total length of the concatenated message */
991 : len_join=__PLUMED_WRAPPER_STD strlen(join);
992 : e=error;
993 : len=__PLUMED_WRAPPER_STD strlen(plumed_error_what(*e));
994 : while(e->nested) {
995 : e=e->nested;
996 : len+=len_join+__PLUMED_WRAPPER_STD strlen(plumed_error_what(*e));
997 : }
998 :
999 : /* Allocate the new message */
1000 : new_buffer=__PLUMED_WRAPPER_STATIC_CAST(char*, plumed_malloc(len+1));
1001 : if(new_buffer) {
1002 : /* If allocation was successful, merge the messages */
1003 : new_buffer[0]='\0';
1004 : /* Notice that we have a forward linked list but we need to go through that in backward order
1005 : (inner to outer). To do that without allocating an additional array, we use a recursive
1006 : function.
1007 : */
1008 : assert(error->nested);
1009 : plumed_error_recursive_merge(error->nested,new_buffer,join,&len);
1010 : __PLUMED_WRAPPER_STD strncat(new_buffer,plumed_error_what(*error),len);
1011 : len -= __PLUMED_WRAPPER_STD strlen(plumed_error_what(*error));
1012 : /* we keep track of length of buffer for safety */
1013 : assert(len==0);
1014 : }
1015 : error->what=new_buffer;
1016 :
1017 : /* Deallocate the previous message */
1018 : if(error->what_buffer) plumed_free(error->what_buffer);
1019 : error->what_buffer=new_buffer;
1020 :
1021 : /* Finalize the chain of nested exceptions */
1022 : plumed_error_finalize(*error->nested);
1023 : plumed_free(error->nested);
1024 : error->nested=__PLUMED_WRAPPER_CXX_NULLPTR;
1025 :
1026 : if(!error->what) {
1027 : /* If allocation was not successful, reset to bad_alloc */
1028 : plumed_error_set_bad_alloc(error);
1029 : }
1030 : }
1031 :
1032 : /** Rethrow error (calling abort) */
1033 : __PLUMED_WRAPPER_CXX_NORETURN __PLUMED_WRAPPER_STATIC_INLINE void plumed_error_rethrow(plumed_error h) {
1034 : if(h.nested) plumed_error_merge_with_nested(&h);
1035 : __PLUMED_WRAPPER_STD fprintf(stderr,"Terminate due to exception. Code: %d\n%s\n",h.code,plumed_error_what(h));
1036 : __PLUMED_WRAPPER_STD abort();
1037 : }
1038 :
1039 : /** Callback (for internal usage) */
1040 0 : __PLUMED_WRAPPER_STATIC_INLINE void plumed_error_set(void*ptr,int code,const char*what,const void* opt) __PLUMED_WRAPPER_CXX_NOEXCEPT {
1041 : plumed_error* error;
1042 : __PLUMED_WRAPPER_STD size_t len;
1043 : void*const* options;
1044 : plumed_error_filesystem_path path;
1045 :
1046 : error=__PLUMED_WRAPPER_STATIC_CAST(plumed_error*, ptr);
1047 :
1048 0 : error->code=code;
1049 0 : error->error_code=0;
1050 0 : len=__PLUMED_WRAPPER_STD strlen(what);
1051 0 : error->what_buffer=__PLUMED_WRAPPER_STATIC_CAST(char*, plumed_malloc(len+1));
1052 0 : if(!error->what_buffer) {
1053 0 : plumed_error_set_bad_alloc(error);
1054 0 : return;
1055 : }
1056 :
1057 : __PLUMED_WRAPPER_STD strncpy(error->what_buffer,what,len+1);
1058 0 : error->what=error->what_buffer;
1059 :
1060 : /* interpret optional arguments */
1061 0 : if(opt) {
1062 : options=__PLUMED_WRAPPER_STATIC_CAST(void*const*, opt);
1063 0 : while(*options) {
1064 : /* c: error code */
1065 0 : if(*(__PLUMED_WRAPPER_STATIC_CAST(const char*,*options))=='c' && *(options+1)) {
1066 0 : error->error_code=*(__PLUMED_WRAPPER_STATIC_CAST(const int*,*(options+1)));
1067 0 : break;
1068 : }
1069 0 : options+=2;
1070 : }
1071 :
1072 : options=__PLUMED_WRAPPER_STATIC_CAST(void*const*,opt);
1073 0 : while(*options) {
1074 : /* C: error_category */
1075 0 : if(*(__PLUMED_WRAPPER_STATIC_CAST(char*, *options))=='C' && *(options+1)) {
1076 0 : error->error_category=*(__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 : /* path 1 */
1085 0 : if(*(__PLUMED_WRAPPER_STATIC_CAST(char*, *options))=='p' && *(options+1)) {
1086 0 : path=*__PLUMED_WRAPPER_STATIC_CAST(plumed_error_filesystem_path*,*(options+1));
1087 0 : error->path1.ptr=plumed_malloc(path.numbytes);
1088 0 : if(!error->path1.ptr) {
1089 0 : plumed_error_set_bad_alloc(error);
1090 0 : return;
1091 : }
1092 0 : error->path1.numbytes=path.numbytes;
1093 : __PLUMED_WRAPPER_STD memcpy(error->path1.ptr,path.ptr,path.numbytes);
1094 : break;
1095 : }
1096 0 : options+=2;
1097 : }
1098 :
1099 : options=__PLUMED_WRAPPER_STATIC_CAST(void*const*, opt);
1100 0 : while(*options) {
1101 : /* path 2 */
1102 0 : if(*(__PLUMED_WRAPPER_STATIC_CAST(char*, *options))=='q' && *(options+1)) {
1103 0 : path=*__PLUMED_WRAPPER_STATIC_CAST(plumed_error_filesystem_path*,*(options+1));
1104 0 : error->path2.ptr=plumed_malloc(path.numbytes);
1105 0 : if(!error->path2.ptr) {
1106 0 : plumed_error_set_bad_alloc(error);
1107 0 : return;
1108 : }
1109 0 : error->path2.numbytes=path.numbytes;
1110 : __PLUMED_WRAPPER_STD memcpy(error->path2.ptr,path.ptr,path.numbytes);
1111 : break;
1112 : }
1113 0 : options+=2;
1114 : }
1115 :
1116 : options=__PLUMED_WRAPPER_STATIC_CAST(void*const*, opt);
1117 0 : while(*options) {
1118 : /* n: nested exception */
1119 0 : if(*(__PLUMED_WRAPPER_STATIC_CAST(char*, *options))=='n' && *(options+1)) {
1120 : /* notice that once this is allocated it is guaranteed to be deallocated by the recursive destructor */
1121 0 : error->nested=__PLUMED_WRAPPER_STATIC_CAST(plumed_error*, plumed_malloc(sizeof(plumed_error)));
1122 : /* this is if malloc fails */
1123 0 : if(!error->nested) {
1124 0 : plumed_error_set_bad_alloc(error);
1125 0 : break;
1126 : }
1127 : plumed_error_init(__PLUMED_WRAPPER_STATIC_CAST(plumed_error*,error->nested));
1128 : /* plumed will make sure to only use this if it is not null */
1129 0 : *__PLUMED_WRAPPER_STATIC_CAST(void**,*(options+1))=error->nested;
1130 0 : break;
1131 : }
1132 0 : options+=2;
1133 : }
1134 : }
1135 : }
1136 :
1137 : /** \relates plumed
1138 : \brief Constructor
1139 :
1140 : Constructs a plumed object.
1141 :
1142 : Notice that if you are linking against libplumedWrapper.a, if you are
1143 : using a code patched in runtime mode, or if you are including the `Plumed.c`
1144 : file directly in your code, this constructor might return an invalid plumed
1145 : object. In particular, this could happen if the `PLUMED_KERNEL` environment
1146 : variable is not set or set incorrectly. In order to detect an incorrect
1147 : plumed object you might use \ref plumed_valid() on the resulting object.
1148 : Alternatively, if you use \ref plumed_cmd() on an invalid plumed object the code will exit.
1149 : Also notice that to avoid memory leaks you should call \ref plumed_finalize()
1150 : to finalize a plumed object even if it is invalid:
1151 : \verbatim
1152 : plumed p=plumed_create();
1153 : if(!plumed_valid(p)) {
1154 : // this will happen if the PLUMED_KERNEL variable is not set correctly
1155 : plumed_finalize(p);
1156 : return whatever;
1157 : }
1158 : \endverbatim
1159 :
1160 : \return The constructed plumed object
1161 : */
1162 : __PLUMED_WRAPPER_C_BEGIN
1163 : plumed plumed_create(void);
1164 : __PLUMED_WRAPPER_C_END
1165 :
1166 : /** \relates plumed
1167 : \brief Constructor from path. Available as of PLUMED 2.5
1168 :
1169 : It tries to construct a plumed object loading the kernel located at path.
1170 : Notice that it could leave the resulting object in an invalid state.
1171 : In order to detect an invalid
1172 : plumed object you might use \ref plumed_valid() on the resulting object.
1173 : Alternatively, if you use \ref plumed_cmd() on an invalid plumed object the code will exit.
1174 :
1175 : Also notice that to avoid memory leaks you should call \ref plumed_finalize()
1176 : to finalize a plumed object even if it is invalid.
1177 : \verbatim
1178 : plumed p=plumed_create(path);
1179 : if(!plumed_valid(p)) {
1180 : // this will happen if the path argument is not set correctly
1181 : plumed_finalize(p);
1182 : return whatever;
1183 : }
1184 : \endverbatim
1185 :
1186 : \return The constructed plumed object
1187 : */
1188 : __PLUMED_WRAPPER_C_BEGIN
1189 : plumed plumed_create_dlopen(const char*path);
1190 : __PLUMED_WRAPPER_C_END
1191 :
1192 :
1193 : /**
1194 : \brief Constructor from path. Available as of PLUMED 2.5
1195 :
1196 : Same as \ref plumed_create_dlopen, but also allows to specify the mode for dlopen.
1197 :
1198 : \warning
1199 : Use with care, since not all the possible modes work correctly with PLUMED.
1200 : */
1201 : __PLUMED_WRAPPER_C_BEGIN
1202 : plumed plumed_create_dlopen2(const char*path,int mode);
1203 : __PLUMED_WRAPPER_C_END
1204 :
1205 : /**
1206 : \brief Constructor from dlopen handle. Available as of PLUMED 2.8
1207 :
1208 : Same as \ref plumed_create_dlopen, but it acts on an already loaded library.
1209 : This allows to separate the library loading from the construction of the
1210 : plumed object. By using this function, the caller takes the responsibility
1211 : to later use dlclose on this handle.
1212 : */
1213 : __PLUMED_WRAPPER_C_BEGIN
1214 : plumed plumed_create_dlsym(void* dlhandle);
1215 : __PLUMED_WRAPPER_C_END
1216 :
1217 : /** \relates plumed
1218 : Create a new reference to an existing object, increasing its reference count. Available as of PLUMED 2.5
1219 :
1220 : Use it to increase by one the reference count of a plumed object.
1221 : The resulting pointer might be identical to the one passed as an
1222 : argument, but the reference count will be incremented by one.
1223 : Notice that you should finalize the resulting object.
1224 : \verbatim
1225 : plumed p1;
1226 : plumed p2;
1227 : p1=plumed_create();
1228 : p2=plumed_create_reference(p1);
1229 : plumed_finalize(p1);
1230 : // now you can still use p2
1231 : plumed_cmd(p2,"init",NULL);
1232 : plumed_finalize(p2);
1233 : // now the underlying object is destroyed.
1234 : \endverbatim
1235 :
1236 : If the `p` object is invalid, also the returned object will be invalid.
1237 :
1238 : \param p The plumed object that will be referenced to.
1239 : \return The constructed plumed object
1240 : */
1241 :
1242 : __PLUMED_WRAPPER_C_BEGIN
1243 : plumed plumed_create_reference(plumed p);
1244 : __PLUMED_WRAPPER_C_END
1245 :
1246 : /** \relates plumed
1247 : \brief Create a new reference to an existing object passed as a void pointer, increasing its reference count. Available as of PLUMED 2.5
1248 :
1249 : \return The constructed plumed object
1250 : */
1251 :
1252 : __PLUMED_WRAPPER_C_BEGIN
1253 : plumed plumed_create_reference_v(void*v);
1254 : __PLUMED_WRAPPER_C_END
1255 :
1256 : /** \relates plumed
1257 : \brief Create a new reference to an existing object passed as a fortran string, 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_f(const char*f);
1264 : __PLUMED_WRAPPER_C_END
1265 :
1266 : /** \relates plumed
1267 : \brief Constructor as invalid. Available as of PLUMED 2.5
1268 :
1269 : Can be used to create an object in the same state as if it was returned by
1270 : plumed_create_dlopen with an incorrect path (or plumed_create using runtime binding
1271 : and an incorrect PLUMED_KERNEL).
1272 :
1273 : Can be used to initialize a plumed object to a well-defined state without explicitly
1274 : creating it. The resulting object can be checked later with \ref plumed_valid.
1275 : Consider the following example
1276 : \verbatim
1277 : plumed p;
1278 : p=plumed_create_invalid();
1279 : // at this point p is initialized to a well-defined (invalid) state.
1280 : setenv("PLUMED_KERNEL","/path/to/kernel/libplumedKernel.so",1);
1281 : plumed_finalize(p);
1282 : p=plumed_create();
1283 : \endverbatim
1284 :
1285 : \return The constructed plumed object
1286 : */
1287 :
1288 : __PLUMED_WRAPPER_C_BEGIN
1289 : plumed plumed_create_invalid();
1290 : __PLUMED_WRAPPER_C_END
1291 :
1292 : /** \relates plumed
1293 : \brief Tells p to execute a command.
1294 :
1295 : If the object is not valid (see \ref plumed_valid), this command will exit.
1296 :
1297 : \param p The plumed object on which command is acting
1298 : \param key The name of the command to be executed
1299 : \param val The argument. It is declared as const to allow calls like plumed_cmd(p,"A","B"),
1300 : but for some choice of key it can change the content.
1301 :
1302 : Notice that within PLUMED we use a const_cast to remove any const qualifier from the second
1303 : argument of \ref plumed_cmd.
1304 :
1305 : In some cases val can be omitted: just pass a NULL pointer (in C++, val is optional and can be omitted,
1306 : or you can equivalently pass NULL or nullptr).
1307 : The set of possible keys is the real API of the plumed library, and will be expanded with time.
1308 : New commands will be added, but backward compatibility will be retained as long as possible.
1309 : */
1310 :
1311 : __PLUMED_WRAPPER_C_BEGIN
1312 : void plumed_cmd(plumed p,const char*key,const void*val);
1313 : __PLUMED_WRAPPER_C_END
1314 :
1315 : /**
1316 : \relates plumed
1317 : \brief Same as \ref plumed_cmd, but does not throw exceptions.
1318 :
1319 : This function is meant to be used when errors should be handled explicitly.
1320 : if an exception is raised within PLUMED, the function nothrow.handler() will
1321 : be called with arguments (nothrow.ptr,code,message,opt). This allows the C++ interface
1322 : to correctly rethrow exceptions, but might be used from C as well. opt can be used
1323 : to pass further information (not used yet).
1324 : */
1325 :
1326 : __PLUMED_WRAPPER_C_BEGIN
1327 : void plumed_cmd_nothrow(plumed p,const char*key,const void*val,plumed_nothrow_handler nothrow);
1328 : __PLUMED_WRAPPER_C_END
1329 :
1330 : __PLUMED_WRAPPER_C_BEGIN
1331 : void plumed_cmd_safe_nothrow(plumed p,const char*key,plumed_safeptr,plumed_nothrow_handler nothrow);
1332 : __PLUMED_WRAPPER_C_END
1333 :
1334 : __PLUMED_WRAPPER_C_BEGIN
1335 : void plumed_cmd_safe(plumed p,const char*key,plumed_safeptr);
1336 : __PLUMED_WRAPPER_C_END
1337 :
1338 : /** \relates plumed
1339 : \brief Destructor.
1340 :
1341 : It must be used for any object created using \ref plumed_create(),
1342 : even if the created object is not valid.
1343 :
1344 : \param p The plumed object to be deallocated
1345 : */
1346 :
1347 : __PLUMED_WRAPPER_C_BEGIN
1348 : void plumed_finalize(plumed p);
1349 : __PLUMED_WRAPPER_C_END
1350 :
1351 : /** \relates plumed
1352 : \brief Check if plumed is installed (for runtime binding).
1353 :
1354 : Notice that this is equivalent to creating a dummy object and checking if it is valid.
1355 :
1356 : \verbatim
1357 : // this:
1358 : //int a=plumed_installed();
1359 : // is equivalent to this:
1360 :
1361 : plumed p=plumed_create();
1362 : int a=plumed_valid(p);
1363 : plumed_finalize(p);
1364 :
1365 : \endverbatim
1366 :
1367 : This function is mostly provided for compatibility with PLUMED 2.4, where \ref plumed_valid()
1368 : was not available. Using \ref plumed_valid() is now preferred since it creates a single object
1369 : instead of creating a dummy object that is then discarded.
1370 :
1371 : \return 1 if plumed is installed, 0 otherwise
1372 : */
1373 :
1374 : __PLUMED_WRAPPER_C_BEGIN
1375 : int plumed_installed(void);
1376 : __PLUMED_WRAPPER_C_END
1377 :
1378 : /** \relates plumed
1379 : \brief Check if plumed object is valid. Available as of PLUMED 2.5
1380 :
1381 : It might return false if plumed is not available at runtime.
1382 :
1383 : \return 1 if plumed is valid, 0 otherwise
1384 : */
1385 :
1386 : __PLUMED_WRAPPER_C_BEGIN
1387 : int plumed_valid(plumed p);
1388 : __PLUMED_WRAPPER_C_END
1389 :
1390 : /** \relates plumed
1391 : \brief Returns the number of references to the underlying object. Available as of PLUMED 2.5.
1392 : */
1393 :
1394 : __PLUMED_WRAPPER_C_BEGIN
1395 : int plumed_use_count(plumed p);
1396 : __PLUMED_WRAPPER_C_END
1397 :
1398 :
1399 : /* routines to convert char handler from/to plumed objects */
1400 :
1401 : /** \related plumed
1402 : \brief Converts a C handler to a FORTRAN handler
1403 :
1404 : \param p The C handler
1405 : \param c The FORTRAN handler (a char[32])
1406 :
1407 : This function can be used to convert a plumed object created in C to
1408 : a plumed handler that can be used in FORTRAN. Notice that the reference counter
1409 : is not incremented. In other words, the FORTRAN object will be a weak reference.
1410 : If you later finalize the C handler, the FORTRAN handler will be invalid.
1411 : \verbatim
1412 : #include <plumed/wrapper/Plumed.h>
1413 : int main(int argc,char*argv[]){
1414 : plumed p;
1415 : p=plumed_create();
1416 : char fortran_handler[32];
1417 : plumed_c2f(p,fortran_handler);
1418 : printf("DEBUG: this is a string representation for the plumed handler: %s\n",fortran_handler);
1419 : fortran_routine(fortran_handler);
1420 : plumed_finalize(p);
1421 : return 0;
1422 : }
1423 : \endverbatim
1424 : Here `fortran_routine` is a routine implemented in FORTRAN that manipulates the
1425 : fortran_handler.
1426 : */
1427 :
1428 : __PLUMED_WRAPPER_C_BEGIN
1429 : void plumed_c2f(plumed p,char* c);
1430 : __PLUMED_WRAPPER_C_END
1431 :
1432 : /** \related plumed
1433 : \brief Converts a FORTRAN handler to a C handler
1434 : \param c The FORTRAN handler (a char[32])
1435 : \return The C handler
1436 :
1437 : This function can be used to convert a plumed object created in FORTRAN
1438 : to a plumed handler that can be used in C. Notice that the reference counter
1439 : is not incremented. In other words, the C object will be a weak reference.
1440 : If you later finalize the FORTRAN handler, the C handler will be invalid.
1441 : \verbatim
1442 : void c_routine(char handler[32]){
1443 : plumed p;
1444 : p=plumed_f2c(handler);
1445 : plumed_cmd(p,"init",NULL);
1446 : }
1447 : \endverbatim
1448 : Here `c_routine` is a C function that can be called from FORTRAN
1449 : and interact with the provided plumed handler.
1450 : */
1451 :
1452 : __PLUMED_WRAPPER_C_BEGIN
1453 : plumed plumed_f2c(const char* c);
1454 : __PLUMED_WRAPPER_C_END
1455 :
1456 : /** \related plumed
1457 : \brief Converts a plumed object to a void pointer. Available as of PLUMED 2.5.
1458 :
1459 : It returns a void pointer that can be converted back to a plumed object using \ref plumed_v2c.
1460 : When compiling without NDEBUG, it checks if the plumed object was properly created.
1461 : Notice that an invalid object (see \ref plumed_valid) can be converted to void* and back.
1462 :
1463 : Can be used to store a reference to a plumed object without including the Plumed.h header.
1464 : */
1465 :
1466 : __PLUMED_WRAPPER_C_BEGIN
1467 : void* plumed_c2v(plumed p);
1468 : __PLUMED_WRAPPER_C_END
1469 :
1470 :
1471 : /** \related plumed
1472 : \brief Converts a void pointer to a plumed object. Available as of PLUMED 2.5.
1473 :
1474 : It returns a plumed object from a void pointer obtained with \ref plumed_c2v.
1475 : When compiling without NDEBUG, it checks if the plumed object was properly created.
1476 :
1477 : Can be used to store a reference to a plumed object without including the Plumed.h header.
1478 : */
1479 :
1480 : __PLUMED_WRAPPER_C_BEGIN
1481 : plumed plumed_v2c(void*);
1482 : __PLUMED_WRAPPER_C_END
1483 :
1484 : #if ! defined( __cplusplus) /*{*/
1485 :
1486 : #if __PLUMED_WRAPPER_C_TYPESAFE /*{*/
1487 :
1488 : #define __PLUMED_WRAPPER_C_TYPESAFE_INNER(type_,typen_,flags_) \
1489 : static inline void plumed_cmdnse_ ## typen_(plumed p,const char*key,type_*ptr, size_t nelem, const size_t* shape,plumed_error* error) { \
1490 : plumed_safeptr safe; \
1491 : plumed_nothrow_handler nothrow; \
1492 : safe.ptr=ptr; \
1493 : safe.nelem=nelem; \
1494 : safe.shape=__PLUMED_WRAPPER_STATIC_CAST(const size_t*, shape); \
1495 : safe.flags=flags_; \
1496 : safe.opt=NULL; \
1497 : if(error) { \
1498 : plumed_error_init(error); \
1499 : nothrow.ptr=error; \
1500 : nothrow.handler=plumed_error_set; \
1501 : plumed_cmd_safe_nothrow(p,key,safe,nothrow); \
1502 : } else { \
1503 : plumed_cmd_safe(p,key,safe); \
1504 : } \
1505 : } \
1506 : static inline void plumed_cmdne_ ## typen_(plumed p,const char*key,type_*ptr, size_t nelem, plumed_error* error) { \
1507 : plumed_cmdnse_ ## typen_(p,key,ptr,nelem,NULL,error); \
1508 : } \
1509 : static inline void plumed_cmdse_ ## typen_(plumed p,const char*key,type_*ptr, const size_t* shape, plumed_error* error) { \
1510 : plumed_cmdnse_ ## typen_(p,key,ptr,0,shape,error); \
1511 : } \
1512 : static inline void plumed_cmdn_ ## typen_(plumed p,const char*key,type_*ptr, size_t nelem) { \
1513 : plumed_cmdnse_ ## typen_(p,key,ptr,nelem,NULL,NULL); \
1514 : } \
1515 : static inline void plumed_cmds_ ## typen_(plumed p,const char*key,type_*ptr, const size_t* shape) { \
1516 : plumed_cmdnse_ ## typen_(p,key,ptr,0,shape,NULL); \
1517 : } \
1518 : static inline void plumed_cmde_ ## typen_(plumed p,const char*key,type_*ptr, plumed_error* error) { \
1519 : plumed_cmdnse_ ## typen_(p,key,ptr,0,NULL,error); \
1520 : }
1521 :
1522 : #define __PLUMED_WRAPPER_C_TYPESAFE_OUTER(type,type_,code,size) \
1523 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type, type_ ## _p, size | (0x10000*(code)) | (0x2000000*2)) \
1524 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type const, type_ ## _c, size | (0x10000*(code)) | (0x2000000*3)) \
1525 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type*, type_ ## _pp, size | (0x10000*(code)) | (0x2000000*4)) \
1526 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type*const, type_ ## _pc, size | (0x10000*(code)) | (0x2000000*5)) \
1527 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type const*, type_ ## _cp, size | (0x10000*(code)) | (0x2000000*6)) \
1528 : __PLUMED_WRAPPER_C_TYPESAFE_INNER(type const*const, type_ ## _cc, size | (0x10000*(code)) | (0x2000000*7))
1529 :
1530 : #define __PLUMED_WRAPPER_C_TYPESAFE_EMPTY(type,type_,code) __PLUMED_WRAPPER_C_TYPESAFE_OUTER(type,type_,code,0)
1531 :
1532 : #define __PLUMED_WRAPPER_C_TYPESAFE_SIZED(type,type_,code) \
1533 : __PLUMED_WRAPPER_C_TYPESAFE_OUTER(type,type_,code,sizeof(type)) \
1534 : static inline void plumed_cmdnse_ ## type_ ## _v(plumed p,const char*key,type val, size_t nelem, const size_t* shape, plumed_error* error) { \
1535 : plumed_safeptr safe; \
1536 : plumed_nothrow_handler nothrow; \
1537 : (void) nelem; \
1538 : (void) shape; \
1539 : safe.ptr=&val; \
1540 : safe.nelem=1; \
1541 : safe.shape=NULL; \
1542 : safe.flags=sizeof(type) | (0x10000*(code)) | (0x2000000*1); \
1543 : safe.opt=NULL; \
1544 : if(error) { \
1545 : plumed_error_init(error); \
1546 : nothrow.ptr=error; \
1547 : nothrow.handler=plumed_error_set; \
1548 : plumed_cmd_safe_nothrow(p,key,safe,nothrow); \
1549 : } else { \
1550 : plumed_cmd_safe(p,key,safe); \
1551 : } \
1552 : } \
1553 : static inline void plumed_cmdne_ ## type_ ## _v(plumed p,const char*key,type val, size_t nelem, plumed_error* error) { \
1554 : plumed_cmdnse_ ## type_ ## _v(p,key,val,nelem,NULL,error); \
1555 : } \
1556 : static inline void plumed_cmdse_ ## type_ ## _v(plumed p,const char*key,type val, const size_t* shape, plumed_error* error) { \
1557 : plumed_cmdnse_ ## type_ ## _v(p,key,val,0,shape,error); \
1558 : } \
1559 : static inline void plumed_cmdn_ ## type_ ## _v(plumed p,const char*key,type val, size_t nelem) { \
1560 : plumed_cmdnse_ ## type_ ## _v(p,key,val,nelem,NULL,NULL); \
1561 : } \
1562 : static inline void plumed_cmds_ ## type_ ## _v(plumed p,const char*key,type val, const size_t* shape) { \
1563 : plumed_cmdnse_ ## type_ ## _v(p,key,val,0,shape,NULL); \
1564 : } \
1565 : static inline void plumed_cmde_ ## type_ ## _v(plumed p,const char*key,type val, plumed_error* error) { \
1566 : plumed_cmdnse_ ## type_ ## _v(p,key,val,0,NULL,error); \
1567 : }
1568 :
1569 : #define __PLUMED_WRAPPER_C_GENERIC1(flavor,type,typen_) \
1570 : type: plumed_ ## flavor ## _ ## typen_,
1571 :
1572 : #define __PLUMED_WRAPPER_C_GENERIC_EMPTY(flavor,type,type_) \
1573 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type*, type_ ## _p) \
1574 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type const*, type_ ## _c) \
1575 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type**, type_ ## _pp) \
1576 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type*const*, type_ ## _pc) \
1577 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type const**, type_ ## _cp) \
1578 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type const*const*, type_ ## _cc)
1579 :
1580 : #define __PLUMED_WRAPPER_C_GENERIC2(flavor,type,type_) \
1581 : __PLUMED_WRAPPER_C_GENERIC_EMPTY(flavor,type,type_) \
1582 : __PLUMED_WRAPPER_C_GENERIC1(flavor,type, type_ ## _v)
1583 :
1584 : /// Here we create all the required instances
1585 : /// 1: void
1586 : /// 3: integral
1587 : /// 4: floating
1588 : /// 5: FILE
1589 : /// 0x100: unsigned
1590 : __PLUMED_WRAPPER_C_TYPESAFE_EMPTY(void,void,1)
1591 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(char,char,(CHAR_MIN==0)*0x100+3)
1592 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(unsigned char,unsigned_char,0x100+3)
1593 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(signed char,signed_char,0x100+3)
1594 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(short,short,3)
1595 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(unsigned short,unsigned_short,0x100+3)
1596 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(int,int,3)
1597 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(unsigned int,unsigned_int,0x100+3)
1598 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(long,long,3)
1599 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(unsigned long,unsigned_long,0x100+3)
1600 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(long long,long_long,3)
1601 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(unsigned long long,unsigned_long_long,0x100+3)
1602 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(float,float,4)
1603 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(double,double,4)
1604 : __PLUMED_WRAPPER_C_TYPESAFE_SIZED(long double,long_double,4)
1605 : __PLUMED_WRAPPER_C_TYPESAFE_EMPTY(FILE,FILE,5)
1606 :
1607 : static inline void plumed_cmd_null_e(plumed p,const char*key,plumed_error* error,int ignore) {
1608 : (void) ignore;
1609 : plumed_cmde_void_p(p,key,NULL,error);
1610 : }
1611 :
1612 : #define plumed_cmdnse_inner(flavor,val) _Generic((val), \
1613 : __PLUMED_WRAPPER_C_GENERIC_EMPTY(flavor,void,void) \
1614 : __PLUMED_WRAPPER_C_GENERIC2(flavor,char,char) \
1615 : __PLUMED_WRAPPER_C_GENERIC2(flavor,unsigned char,unsigned_char) \
1616 : __PLUMED_WRAPPER_C_GENERIC2(flavor,signed char,signed_char) \
1617 : __PLUMED_WRAPPER_C_GENERIC2(flavor,short,short) \
1618 : __PLUMED_WRAPPER_C_GENERIC2(flavor,unsigned short,unsigned_short) \
1619 : __PLUMED_WRAPPER_C_GENERIC2(flavor,int,int) \
1620 : __PLUMED_WRAPPER_C_GENERIC2(flavor,unsigned int,unsigned_int) \
1621 : __PLUMED_WRAPPER_C_GENERIC2(flavor,long,long) \
1622 : __PLUMED_WRAPPER_C_GENERIC2(flavor,unsigned long,unsigned_long) \
1623 : __PLUMED_WRAPPER_C_GENERIC2(flavor,long long,long_long) \
1624 : __PLUMED_WRAPPER_C_GENERIC2(flavor,unsigned long long,unsigned_long_long) \
1625 : __PLUMED_WRAPPER_C_GENERIC2(flavor,float,float) \
1626 : __PLUMED_WRAPPER_C_GENERIC2(flavor,double,double) \
1627 : __PLUMED_WRAPPER_C_GENERIC2(flavor,long double,long_double) \
1628 : __PLUMED_WRAPPER_C_GENERIC_EMPTY(flavor,FILE,FILE) \
1629 : default: plumed_ ## flavor ## _void_c)
1630 :
1631 : #define plumed_cmd_2args(p,key) plumed_cmdnse_inner(cmdn,NULL) (p,key,NULL,0)
1632 :
1633 : #define plumed_cmd_3args(p,key,X) _Generic((X), \
1634 : plumed_error*: plumed_cmd_null_e, \
1635 : default: plumed_cmdnse_inner(cmdn,X)) (p,key,X,0)
1636 :
1637 : /* ((X)+(size_t)0): for pointers, no op; for integers, convert to size_t */
1638 : #define plumed_cmd_4args(p,key,val,X) _Generic(((X)+(size_t)0), \
1639 : const size_t *: plumed_cmdnse_inner(cmds,val), \
1640 : size_t *: plumed_cmdnse_inner(cmds,val), \
1641 : size_t: plumed_cmdnse_inner(cmdn,val), \
1642 : plumed_error*: plumed_cmdnse_inner(cmde,val) \
1643 : ) (p,key,val,X)
1644 :
1645 : /* ((X)+(size_t)0): for pointers, no op; for integers, convert to size_t */
1646 : #define plumed_cmd_5args(p,key,val,X,error) _Generic(((X)+(size_t)0), \
1647 : const size_t *: plumed_cmdnse_inner(cmdse,val), \
1648 : size_t *: plumed_cmdnse_inner(cmdse,val), \
1649 : size_t: plumed_cmdnse_inner(cmdne,val) \
1650 : ) (p,key,val,X,error)
1651 :
1652 : #define __PLUMED_WRAPPER_C_GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
1653 : #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__)
1654 :
1655 : #define plumed_gcmd_c11(...) plumed_cmd(plumed_global(),__VA_ARGS__)
1656 :
1657 : #define __PLUMED_WRAPPER_REDEFINE_CMD plumed_cmd_c11
1658 : #define __PLUMED_WRAPPER_REDEFINE_GCMD plumed_gcmd_c11
1659 :
1660 : #endif /*}*/
1661 :
1662 : #endif /*}*/
1663 :
1664 :
1665 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
1666 :
1667 : /* Global C functions are always extern */
1668 : __PLUMED_WRAPPER_EXTERN_C_BEGIN /*{*/
1669 :
1670 : /** \relates plumed
1671 : \brief Retrieves an handler to the global structure.
1672 :
1673 : You can use this if you work on a code that uses the global structure and you want to
1674 : pass to a generic routine an handler to the same structure. E.g.
1675 :
1676 : \verbatim
1677 : plumed p=plumed_global();
1678 : some_routine(p);
1679 : \endverbatim
1680 : */
1681 : extern
1682 : plumed plumed_global(void);
1683 :
1684 : /** \relates plumed
1685 : \brief Check if the global interface has been initialized.
1686 :
1687 : \return 1 if plumed has been initialized, 0 otherwise
1688 : */
1689 : extern
1690 : int plumed_ginitialized(void);
1691 :
1692 : /** \relates plumed
1693 : \brief Constructor for the global interface.
1694 :
1695 : \note Equivalent to plumed_create(), but initialize the static global plumed object
1696 : */
1697 : extern
1698 : void plumed_gcreate(void);
1699 :
1700 : /** \relates plumed
1701 : \brief Tells to the global interface to execute a command.
1702 :
1703 : \param key The name of the command to be executed
1704 : \param val The argument. It is declared as const to allow calls like plumed_gcmd("A","B"),
1705 : but for some choice of key it can change the content
1706 :
1707 : `plumed_gcmd(a,b);` is equivalent to `plumed_cmd(plumed_global(),a,b);`.
1708 : */
1709 : extern
1710 : void plumed_gcmd(const char* key,const void* val);
1711 :
1712 : /** \relates plumed
1713 : \brief Tells to the global interface to execute a command.
1714 :
1715 : \param key The name of the command to be executed
1716 : \param safe A safe pointer
1717 :
1718 : `plumed_gcmd_safe(a,b);` is equivalent to `plumed_cmd_safe(plumed_global(),a,b);`.
1719 : */
1720 : extern
1721 : void plumed_gcmd_safe(const char* key,plumed_safeptr);
1722 :
1723 : /** \relates plumed
1724 : \brief Destructor for the global interface.
1725 :
1726 : `plumed_gfinalize(a,b);` is similar to `plumed_finalize(plumed_global(),a,b);`, but not completely
1727 : equivalent. In particular, plumed_gfinalize() also makes sure that the global object
1728 : is reset to its initial status. After calling it, \ref plumed_ginitialized() will thus return 0.
1729 : */
1730 : extern
1731 : void plumed_gfinalize(void);
1732 :
1733 : /** \relates plumed
1734 : \brief Check if global plumed object is valid. Available as of PLUMED 2.5
1735 :
1736 : It might return zero if plumed is not available at runtime.
1737 :
1738 : \return 1 if plumed is valid, 0 otherwise.
1739 : */
1740 : extern
1741 : int plumed_gvalid();
1742 :
1743 : __PLUMED_WRAPPER_EXTERN_C_END /*}*/
1744 :
1745 : #endif /*}*/
1746 :
1747 : #if defined( __cplusplus) && __PLUMED_WRAPPER_CXX /*{*/
1748 :
1749 : #if __PLUMED_WRAPPER_CXX_STD
1750 : #include <cstdlib> /* NULL getenv */
1751 : #include <cstddef> /* nullptr_t */
1752 : #include <cstring> /* strncat strlen */
1753 : #include <cassert> /* assert */
1754 : #include <climits> /* CHAR_MIN */
1755 : #else
1756 : #include <stddef.h>
1757 : #include <stdlib.h>
1758 : #include <string.h>
1759 : #include <assert.h>
1760 : #include <limits.h>
1761 : #endif
1762 :
1763 : #include <exception> /* exception bad_exception */
1764 : #include <stdexcept> /* runtime_error logic_error invalid_argument domain_error length_error out_of_range range_error overflow_error underflow_error */
1765 : #include <string> /* string */
1766 : #include <ios> /* iostream_category (C++11) ios_base::failure (C++11 and C++<11) */
1767 : #include <new> /* bad_alloc bad_array_new_length (C++11) */
1768 : #include <typeinfo> /* bad_typeid bad_cast */
1769 : #include <limits> /* numeric_limits */
1770 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
1771 : #include <system_error> /* system_error generic_category system_category */
1772 : #include <future> /* future_category */
1773 : #include <memory> /* bad_weak_ptr */
1774 : #include <functional> /* bad_function_call */
1775 : #include <regex> /* regex_error */
1776 : #endif
1777 : #if __cplusplus >= 201703L && __PLUMED_WRAPPER_LIBCXX17
1778 : #include <any> /* bad_any_cast */
1779 : #include <variant> /* bad_variant_access */
1780 : #include <optional> /* bad_optional_access */
1781 : #include <filesystem> /* filesystem_error */
1782 : #endif
1783 :
1784 : #if __cplusplus >= 201703L
1785 : #include <memory> /* unique_ptr */
1786 : #include <string_view> /* string_view */
1787 : #endif
1788 :
1789 : #if __cplusplus > 199711L
1790 : #include <array> /* array */
1791 : #include <initializer_list> /* initializer_list */
1792 : #include <type_traits> /* std::enable_if */
1793 : #endif
1794 :
1795 : /* C++ interface is hidden in PLMD namespace (same as plumed library) */
1796 : namespace PLMD {
1797 :
1798 : /* Optionally, it is further hidden in an anonymous namespace */
1799 :
1800 : __PLUMED_WRAPPER_ANONYMOUS_BEGIN /*{*/
1801 :
1802 : /**
1803 : Retrieve PLUMED_EXCEPTIONS_DEBUG (internal utility).
1804 :
1805 : This function should not be used by external programs. It is defined
1806 : as inline static so that it can store a static variable (for quicker access)
1807 : without adding a unique global symbol to a library including this header file.
1808 : */
1809 0 : inline static bool PlumedGetenvExceptionsDebug() __PLUMED_WRAPPER_CXX_NOEXCEPT {
1810 0 : static const char* res=__PLUMED_WRAPPER_STD getenv("PLUMED_EXCEPTIONS_DEBUG");
1811 0 : return res;
1812 : }
1813 :
1814 : #if __cplusplus > 199711L
1815 :
1816 : /**
1817 :
1818 : We use a separate namespace here instead of hiding these classes in the Plumed
1819 : class, because some of these structs might be specialized by the user.
1820 :
1821 : */
1822 : namespace wrapper {
1823 :
1824 : /// This is to replace c++17 std::void_t
1825 : template<typename... Ts>
1826 : struct make_void { using type = void; };
1827 : template<typename... Ts>
1828 : using void_t = typename make_void<Ts...>::type;
1829 :
1830 : /// Primary template, assumes T does not have both size() and data() methods
1831 : template<typename T, typename = void>
1832 : struct has_size_and_data : std::false_type {};
1833 :
1834 : /// Specialization for types T that do have both size() and data() methods
1835 : template<typename T>
1836 : struct has_size_and_data<T, void_t<decltype(std::declval<T>().size()), decltype(std::declval<T>().data())>> : std::true_type {};
1837 :
1838 : /// Primary template, assumes T is not a custom structure.
1839 : /// Can be specialized to inform about custom structures
1840 : template<typename T>
1841 : struct is_custom_array : std::false_type {
1842 : typedef void value_type;
1843 : };
1844 :
1845 : /// Template specialization for std::array
1846 : template<typename T, std::size_t N>
1847 : struct is_custom_array<std::array<T,N>> : std::true_type {
1848 : using value_type = typename std::array<T,N>::value_type;
1849 : };
1850 :
1851 : /// Template specialization for C arrays.
1852 : /// Note: we have to use it as wrapper::is_custom_array<typename std::remove_reference<T>::type>::value
1853 : /// because C arrays are only passed by reference!
1854 : template<typename T, std::size_t N>
1855 : struct is_custom_array<T[N]> : std::true_type {
1856 : using value_type = typename std::remove_reference<decltype(std::declval<T[N]>()[0])>::type;
1857 : };
1858 :
1859 : /// Generic utility to retrieve the size of a container
1860 : template<typename T>
1861 : inline std::size_t size(const T&obj) {
1862 : return obj.size();
1863 : }
1864 :
1865 : /// Specialization for std::string, which returns size()+1, which includes the terminating null character
1866 : template<>
1867 : inline std::size_t size(const std::string &obj) {
1868 : return obj.size()+1;
1869 : }
1870 :
1871 : /// Report the size of a custom_array.
1872 : /// typename std::remove_reference<T>::type is needed because C arrays are passed by reference
1873 : template<typename T, typename std::enable_if<wrapper::is_custom_array<typename std::remove_reference<T>::type>::value, int>::type = 0>
1874 : inline std::size_t custom_array_size() {
1875 : using value_type = typename wrapper::is_custom_array<typename std::remove_reference<T>::type>::value_type;
1876 : constexpr std::size_t value_size=sizeof(value_type);
1877 : static_assert(value_size>0,"cannot use custom arrays of void types");
1878 : static_assert(sizeof(T)%value_size==0,"custom array has incorrect size");
1879 : return sizeof(T)/sizeof(value_type);
1880 : }
1881 :
1882 : /// Cast a pointer to a custom_array to a pointer of its value_type.
1883 : /// typename std::remove_reference<T>::type is needed because C arrays are passed by reference
1884 : template<typename T, typename std::enable_if<wrapper::is_custom_array<typename std::remove_reference<T>::type>::value, int>::type = 0>
1885 : inline typename wrapper::is_custom_array<T>::value_type* custom_array_cast(T* val) {
1886 : using value_type = typename wrapper::is_custom_array<typename std::remove_reference<T>::type>::value_type;
1887 : return reinterpret_cast<value_type*>(val);
1888 : }
1889 :
1890 : }
1891 :
1892 : #endif
1893 :
1894 :
1895 : /**
1896 : C++ wrapper for \ref plumed.
1897 :
1898 : This class provides a C++ interface to PLUMED.
1899 : It only containts a \ref plumed object, but wraps it with a number of useful methods.
1900 : All methods are inlined so as to avoid the compilation of an extra c++ file.
1901 :
1902 : */
1903 :
1904 : class Plumed {
1905 : /**
1906 : C structure.
1907 : */
1908 : plumed main;
1909 :
1910 : private:
1911 :
1912 : /**
1913 : This is an internal utility to dispatch exceptions based on the plumed_error object.
1914 :
1915 : It takes information about the exception to be thrown by the passed h object
1916 : and use it to call function f() on the resulting exception. Notice that:
1917 : - this function does not consider if the error is nested.
1918 : - f should be a callable object, so that it can store information
1919 : - f operator() should be a template function so as to act based on the
1920 : type of its argument
1921 :
1922 : New exceptions added here should be kept in sync with core/PlumedMainInitializer.cpp
1923 :
1924 : Notice that this function also finalizes in place plumed_error h, so as to avoid
1925 : memory leaks.
1926 : */
1927 : template<typename F>
1928 0 : __PLUMED_WRAPPER_CXX_NORETURN static void exception_dispatch(plumed_error&h,F f) {
1929 : /* this is required to make sure h is finalized when leaving this function */
1930 : finalize_plumed_error finalize(h);
1931 : /* grab the message */
1932 : const char* msg=plumed_error_what(h);
1933 0 : if(h.code==1) f(Plumed::Invalid(msg));
1934 : /* logic errors */
1935 0 : if(h.code>=10100 && h.code<10200) {
1936 0 : if(h.code>=10105 && h.code<10110) f(::std::invalid_argument(msg));
1937 0 : if(h.code>=10110 && h.code<10115) f(::std::domain_error(msg));
1938 0 : if(h.code>=10115 && h.code<10120) f(::std::length_error(msg));
1939 0 : if(h.code>=10120 && h.code<10125) f(::std::out_of_range(msg));
1940 : #if __cplusplus >= 201703L && __PLUMED_WRAPPER_LIBCXX17
1941 : if(h.code==10125) f(add_buffer_to< ::std::future_error>(::std::future_error(::std::future_errc::broken_promise),msg));
1942 : if(h.code==10126) f(add_buffer_to< ::std::future_error>(::std::future_error(::std::future_errc::future_already_retrieved),msg));
1943 : if(h.code==10127) f(add_buffer_to< ::std::future_error>(::std::future_error(::std::future_errc::promise_already_satisfied),msg));
1944 : if(h.code==10128) f(add_buffer_to< ::std::future_error>(::std::future_error(::std::future_errc::no_state),msg));
1945 : #endif
1946 0 : f(::std::logic_error(msg));
1947 : }
1948 : /* runtime errors */
1949 0 : if(h.code>=10200 && h.code<10300) {
1950 0 : if(h.code>=10205 && h.code<10210) f(::std::range_error(msg));
1951 0 : if(h.code>=10210 && h.code<10215) f(::std::overflow_error(msg));
1952 0 : if(h.code>=10215 && h.code<10220) f(::std::underflow_error(msg));
1953 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
1954 0 : if(h.code==10220) f(::std::system_error(h.error_code,::std::generic_category(),msg));
1955 0 : if(h.code==10221) f(::std::system_error(h.error_code,::std::system_category(),msg));
1956 0 : if(h.code==10222) f(::std::system_error(h.error_code,::std::iostream_category(),msg));
1957 0 : if(h.code==10223) f(::std::system_error(h.error_code,::std::future_category(),msg));
1958 : #endif
1959 : #if __cplusplus >= 201703L && __PLUMED_WRAPPER_LIBCXX17
1960 : if(h.code==10229) {
1961 : ::std::error_code error_code;
1962 : if(h.error_category==1) error_code=::std::error_code(h.error_code,::std::generic_category());
1963 : if(h.error_category==2) error_code=::std::error_code(h.error_code,::std::system_category());
1964 : if(h.error_category==3) error_code=::std::error_code(h.error_code,::std::iostream_category());
1965 : if(h.error_category==4) error_code=::std::error_code(h.error_code,::std::future_category());
1966 :
1967 : if(!h.path1.ptr) {
1968 : f(::std::filesystem::filesystem_error(msg,error_code));
1969 : } else if(!h.path2.ptr) {
1970 : /*
1971 : In principle native_format is a possible value of an enum,
1972 : so should be accessible as ::std::filesystem::path::native_format
1973 : However, some clang versions declare it as enum class. Thus,
1974 : ::std::filesystem::path::format::native_format is more portable.
1975 : */
1976 : f(::std::filesystem::filesystem_error(msg,
1977 : ::std::filesystem::path(::std::filesystem::path::string_type(
1978 : reinterpret_cast<::std::filesystem::path::value_type*>(h.path1.ptr),
1979 : h.path1.numbytes/sizeof(::std::filesystem::path::value_type)
1980 : ),
1981 : ::std::filesystem::path::format::native_format),
1982 : error_code));
1983 : } else {
1984 : f(::std::filesystem::filesystem_error(msg,
1985 : ::std::filesystem::path(::std::filesystem::path::string_type(
1986 : reinterpret_cast<::std::filesystem::path::value_type*>(h.path1.ptr),
1987 : h.path1.numbytes/sizeof(::std::filesystem::path::value_type)
1988 : ),
1989 : ::std::filesystem::path::format::native_format),
1990 : ::std::filesystem::path(::std::filesystem::path::string_type(
1991 : reinterpret_cast<::std::filesystem::path::value_type*>(h.path2.ptr),
1992 : h.path2.numbytes/sizeof(::std::filesystem::path::value_type)
1993 : ),
1994 : ::std::filesystem::path::format::native_format),
1995 : error_code));
1996 : }
1997 : }
1998 : #endif
1999 : if(h.code>=10230 && h.code<10240) {
2000 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2001 : // These cases are probably useless as it looks like this should always be std::iostream_category
2002 0 : if(h.code==10230) f(::std::ios_base::failure(msg,::std::error_code(h.error_code,::std::generic_category())));
2003 0 : if(h.code==10231) f(::std::ios_base::failure(msg,::std::error_code(h.error_code,::std::system_category())));
2004 0 : if(h.code==10232) f(::std::ios_base::failure(msg,::std::error_code(h.error_code,::std::iostream_category())));
2005 0 : if(h.code==10233) f(::std::ios_base::failure(msg,::std::error_code(h.error_code,::std::future_category())));
2006 : #endif
2007 0 : f(::std::ios_base::failure(msg));
2008 : }
2009 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2010 0 : if(h.code==10240) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_collate),msg));
2011 0 : if(h.code==10241) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_ctype),msg));
2012 0 : if(h.code==10242) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_escape),msg));
2013 0 : if(h.code==10243) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_backref),msg));
2014 0 : if(h.code==10244) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_brack),msg));
2015 0 : if(h.code==10245) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_paren),msg));
2016 0 : if(h.code==10246) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_brace),msg));
2017 0 : if(h.code==10247) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_badbrace),msg));
2018 0 : if(h.code==10248) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_range),msg));
2019 0 : if(h.code==10249) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_space),msg));
2020 0 : if(h.code==10250) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_badrepeat),msg));
2021 0 : if(h.code==10251) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_complexity),msg));
2022 0 : if(h.code==10252) f(add_buffer_to< ::std::regex_error>(::std::regex_error(::std::regex_constants::error_stack),msg));
2023 : #endif
2024 0 : f(::std::runtime_error(msg));
2025 : }
2026 : /* "bad" errors */
2027 : /* "< ::" space required in C++ < 11 */
2028 0 : if(h.code>=11000 && h.code<11100) f(add_buffer_to< ::std::bad_typeid>(msg));
2029 0 : if(h.code>=11100 && h.code<11200) {
2030 : #if __cplusplus >= 201703L && __PLUMED_WRAPPER_LIBCXX17
2031 : if(h.code>=11150) f(add_buffer_to< ::std::bad_any_cast>(msg));
2032 : #endif
2033 0 : f(add_buffer_to< ::std::bad_cast>(msg));
2034 : }
2035 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2036 0 : if(h.code>=11200 && h.code<11300) f(add_buffer_to< ::std::bad_weak_ptr>(msg));
2037 0 : if(h.code>=11300 && h.code<11400) f(add_buffer_to< ::std::bad_function_call>(msg));
2038 : #endif
2039 0 : if(h.code>=11400 && h.code<11500) {
2040 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2041 0 : if(h.code>=11410 && h.code<11420) f(add_buffer_to< ::std::bad_array_new_length>(msg));
2042 : #endif
2043 0 : f(add_buffer_to< ::std::bad_alloc>(msg));
2044 : }
2045 0 : if(h.code>=11500 && h.code<11600) f(add_buffer_to< ::std::bad_exception>(msg));
2046 : #if __cplusplus >= 201703L && __PLUMED_WRAPPER_LIBCXX17
2047 : if(h.code>=11600 && h.code<11700) f(add_buffer_to< ::std::bad_optional_access>(msg));
2048 : if(h.code>=11700 && h.code<11800) f(add_buffer_to< ::std::bad_variant_access>(msg));
2049 : #endif
2050 : /* lepton error */
2051 0 : if(h.code>=19900 && h.code<20000) f(Plumed::LeptonException(msg));
2052 : /* plumed exceptions */
2053 0 : if(h.code>=20000 && h.code<30000) {
2054 : /* debug - only raised with debug options */
2055 0 : if(h.code>=20100 && h.code<20200) f(Plumed::ExceptionDebug(msg));
2056 : /* error - runtime check */
2057 0 : if(h.code>=20200 && h.code<20300) f(Plumed::ExceptionError(msg));
2058 : /* error - type error */
2059 0 : if(h.code>=20300 && h.code<20400) f(Plumed::ExceptionTypeError(msg));
2060 0 : f(Plumed::Exception(msg));
2061 : }
2062 : /* fallback for any other exception */
2063 0 : f(add_buffer_to< ::std::exception>(msg));
2064 0 : }
2065 :
2066 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_CXX_ENABLE_NESTED_EXCEPTIONS
2067 : /** Internal class used by exception_dispatch. */
2068 : class rethrow_nested {
2069 : public:
2070 : template<typename E>
2071 : __PLUMED_WRAPPER_CXX_NORETURN void operator()(const E&e) {
2072 0 : std::throw_with_nested(e);
2073 : }
2074 : };
2075 : #endif
2076 :
2077 : /** Internal class used by exception_dispatch. */
2078 : class rethrow_not_nested {
2079 : public:
2080 : template<typename E>
2081 0 : __PLUMED_WRAPPER_CXX_NORETURN void operator()(const E&e) {
2082 0 : throw e;
2083 : }
2084 : };
2085 :
2086 : /** Internal class to simplify plumed_error finalization */
2087 : class finalize_plumed_error {
2088 : plumed_error&e;
2089 : finalize_plumed_error(const finalize_plumed_error&); //not implemented
2090 : public:
2091 0 : __PLUMED_WRAPPER_CXX_EXPLICIT finalize_plumed_error(plumed_error&e):
2092 0 : e(e)
2093 : {}
2094 0 : ~finalize_plumed_error() {
2095 0 : plumed_error_finalize(e);
2096 0 : e.code=0; // make sure it's not finalized again
2097 0 : }
2098 : };
2099 :
2100 : /**
2101 : Recursive function that rethrows an exception with all the nested ones.
2102 :
2103 : In order to do so, we start throwing from the first exception that was originally thrown
2104 : and recursively throw the others using throw_with_nested.
2105 :
2106 : plumed_error h is finalized at exit by the exception_dispatch function, to avoid memory leaks
2107 : */
2108 0 : __PLUMED_WRAPPER_CXX_NORETURN static void rethrow(plumed_error&h) {
2109 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_CXX_ENABLE_NESTED_EXCEPTIONS
2110 : /*
2111 : When using C++11 nested exceptions, we need to rethrow recursively
2112 : */
2113 : try {
2114 0 : if(h.nested) rethrow(*h.nested); /* recursive throw */
2115 0 : } catch(...) {
2116 0 : exception_dispatch(h,rethrow_nested());
2117 0 : }
2118 0 : exception_dispatch(h,rethrow_not_nested());
2119 : #else
2120 : /*
2121 : When using C++<11 exceptions, we merge the message and then throw the resulting exception
2122 : */
2123 : if(h.nested) plumed_error_merge_with_nested(&h);
2124 : exception_dispatch(h,rethrow_not_nested());
2125 : #endif
2126 : }
2127 :
2128 : public:
2129 : /**
2130 : This is a tool to rethrow an error as an exception and finalize the error.
2131 :
2132 : In practice, this makes it possible to write a code like this:
2133 : ```
2134 : Plumed p;
2135 : plumed_error e;
2136 : // store error in e if something wrong happes
2137 : // notice that Plumed (C++) is implicitly converted to plumed (C) when calling plumed_cmd
2138 : plumed_cmd(p,"init",&e);
2139 : // do other things here
2140 : // then throw the exception
2141 : if(e.code) plumed_error_rethrow(e);
2142 :
2143 : It should be used through the macro plumed_error_rethrow.
2144 : ```
2145 : */
2146 : __PLUMED_WRAPPER_CXX_NORETURN static void plumed_error_rethrow_cxx(plumed_error h) {
2147 0 : rethrow(h);
2148 : }
2149 :
2150 : private:
2151 : /**
2152 : Rethrow the current exception.
2153 :
2154 : This is useful in order to handle an exception thrown by a kernel <=2.4.
2155 : Only std exceptions are handled, though some of them are thrown as special
2156 : Plumed exceptions in order to be attached a message.
2157 : */
2158 0 : __PLUMED_WRAPPER_CXX_NORETURN static void rethrow() {
2159 : try {
2160 0 : throw;
2161 0 : } catch(const ::std::bad_exception & e) {
2162 0 : throw add_buffer_to< ::std::bad_exception>(e.what());
2163 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2164 0 : } catch(const ::std::bad_array_new_length & e) {
2165 0 : throw add_buffer_to< ::std::bad_array_new_length>(e.what());
2166 : #endif
2167 0 : } catch(const ::std::bad_alloc & e) {
2168 0 : throw add_buffer_to< ::std::bad_alloc>(e.what());
2169 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2170 0 : } catch(const ::std::bad_function_call & e) {
2171 0 : throw add_buffer_to< ::std::bad_function_call>(e.what());
2172 0 : } catch(const ::std::bad_weak_ptr & e) {
2173 0 : throw add_buffer_to< ::std::bad_weak_ptr>(e.what());
2174 : #endif
2175 0 : } catch(const ::std::bad_cast & e) {
2176 0 : throw add_buffer_to< ::std::bad_cast>(e.what());
2177 0 : } catch(const ::std::bad_typeid & e) {
2178 0 : throw add_buffer_to< ::std::bad_typeid>(e.what());
2179 : // not implemented yet: std::regex_error
2180 : // we do not allow regex yet due to portability problems with gcc 4.8
2181 : // as soon as we transition to using <regex> it should be straightforward to add
2182 0 : } catch(const ::std::ios_base::failure & e) {
2183 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2184 0 : throw ::std::ios_base::failure(e.what(),e.code());
2185 : #else
2186 : throw ::std::ios_base::failure(e.what());
2187 : #endif
2188 : #if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
2189 0 : } catch(const ::std::system_error & e) {
2190 0 : throw ::std::system_error(e.code(),e.what());
2191 : #endif
2192 0 : } catch(const ::std::underflow_error &e) {
2193 0 : throw ::std::underflow_error(e.what());
2194 0 : } catch(const ::std::overflow_error &e) {
2195 0 : throw ::std::overflow_error(e.what());
2196 0 : } catch(const ::std::range_error &e) {
2197 0 : throw ::std::range_error(e.what());
2198 0 : } catch(const ::std::runtime_error & e) {
2199 0 : throw ::std::runtime_error(e.what());
2200 : // not implemented yet: std::future_error
2201 : // not clear how useful it would be.
2202 0 : } catch(const ::std::out_of_range & e) {
2203 0 : throw ::std::out_of_range(e.what());
2204 0 : } catch(const ::std::length_error & e) {
2205 0 : throw ::std::length_error(e.what());
2206 0 : } catch(const ::std::domain_error & e) {
2207 0 : throw ::std::domain_error(e.what());
2208 0 : } catch(const ::std::invalid_argument & e) {
2209 0 : throw ::std::invalid_argument(e.what());
2210 0 : } catch(const ::std::logic_error & e) {
2211 0 : throw ::std::logic_error(e.what());
2212 0 : } catch(const ::std::exception & e) {
2213 0 : throw add_buffer_to< ::std::exception>(e.what());
2214 0 : } catch(...) {
2215 0 : throw add_buffer_to< ::std::bad_exception>("plumed could not translate exception");
2216 0 : }
2217 : }
2218 :
2219 : public:
2220 :
2221 : #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS
2222 : using Exception = PLMD::Exception;
2223 : #else
2224 : /**
2225 : Base class used to rethrow PLUMED exceptions.
2226 : */
2227 : class Exception :
2228 : public ::std::exception
2229 : {
2230 : ::std::string msg;
2231 : public:
2232 0 : __PLUMED_WRAPPER_CXX_EXPLICIT Exception(const char* msg): msg(msg) {}
2233 0 : const char* what() const __PLUMED_WRAPPER_CXX_NOEXCEPT __PLUMED_WRAPPER_CXX_OVERRIDE {return msg.c_str();}
2234 : #if ! (__cplusplus > 199711L)
2235 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2236 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2237 : ~Exception() throw() {}
2238 : #endif
2239 : };
2240 : #endif
2241 :
2242 : #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS
2243 : using ExceptionError = PLMD::ExceptionError;
2244 : #else
2245 : /**
2246 : Used to rethrow a PLMD::ExceptionError
2247 : */
2248 0 : class ExceptionError :
2249 : public Exception {
2250 : public:
2251 0 : __PLUMED_WRAPPER_CXX_EXPLICIT ExceptionError(const char* msg): Exception(msg) {}
2252 : #if ! (__cplusplus > 199711L)
2253 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2254 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2255 : ~ExceptionError() throw() {}
2256 : #endif
2257 : };
2258 : #endif
2259 :
2260 : #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS
2261 : using ExceptionDebug = PLMD::ExceptionDebug;
2262 : #else
2263 : /**
2264 : Used to rethrow a PLMD::ExceptionDebug
2265 : */
2266 0 : class ExceptionDebug :
2267 : public Exception {
2268 : public:
2269 0 : __PLUMED_WRAPPER_CXX_EXPLICIT ExceptionDebug(const char* msg): Exception(msg) {}
2270 : #if ! (__cplusplus > 199711L)
2271 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2272 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2273 : ~ExceptionDebug() throw() {}
2274 : #endif
2275 : };
2276 : #endif
2277 :
2278 : /**
2279 : Thrown when trying to access an invalid plumed object
2280 : */
2281 :
2282 0 : class Invalid :
2283 : public Exception {
2284 : public:
2285 0 : __PLUMED_WRAPPER_CXX_EXPLICIT Invalid(const char* msg): Exception(msg) {}
2286 : #if ! (__cplusplus > 199711L)
2287 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2288 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2289 : ~Invalid() throw() {}
2290 : #endif
2291 : };
2292 :
2293 : #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS
2294 : using ExceptionTypeError = PLMD::ExceptionTypeError;
2295 : #else
2296 : /**
2297 : Thrown when a wrong pointer is passed to the PLUMED interface.
2298 : */
2299 0 : class ExceptionTypeError:
2300 : public Exception {
2301 : public:
2302 0 : __PLUMED_WRAPPER_CXX_EXPLICIT ExceptionTypeError(const char* msg): Exception(msg) {}
2303 : #if ! (__cplusplus > 199711L)
2304 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2305 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2306 : ~ExceptionTypeError() throw() {}
2307 : #endif
2308 : };
2309 : #endif
2310 :
2311 : #if __PLUMED_WRAPPER_CXX_ANONYMOUS_NAMESPACE_PLMD_EXCEPTIONS
2312 : using LeptonException = PLMD::lepton::Exception;
2313 : #else
2314 : /**
2315 : Class used to rethrow Lepton exceptions.
2316 : */
2317 :
2318 : class LeptonException :
2319 : public ::std::exception
2320 : {
2321 : ::std::string msg;
2322 : public:
2323 0 : __PLUMED_WRAPPER_CXX_EXPLICIT LeptonException(const char* msg): msg(msg) {}
2324 0 : const char* what() const __PLUMED_WRAPPER_CXX_NOEXCEPT __PLUMED_WRAPPER_CXX_OVERRIDE {return msg.c_str();}
2325 : #if ! (__cplusplus > 199711L)
2326 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2327 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2328 : ~LeptonException() throw() {}
2329 : #endif
2330 : };
2331 : #endif
2332 :
2333 : private:
2334 : /*
2335 : These exceptions are declared as private as they are not supposed to be
2336 : catched by value. they only exist to allow a buffer to be attached to
2337 : the std::exceptions that do not contain it already.
2338 : Notice that these exceptions are those whose constructor should never throw, and as
2339 : such they use a fixed size buffer.
2340 : */
2341 :
2342 : template<typename T>
2343 0 : class add_buffer_to:
2344 : public T
2345 : {
2346 : char msg[__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER];
2347 0 : void init(const char* msg) __PLUMED_WRAPPER_CXX_NOEXCEPT {
2348 0 : this->msg[0]='\0';
2349 0 : __PLUMED_WRAPPER_STD strncpy(this->msg,msg,__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER);
2350 0 : this->msg[__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER-1]='\0';
2351 0 : if(PlumedGetenvExceptionsDebug() && __PLUMED_WRAPPER_STD strlen(msg) > __PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER-1) __PLUMED_WRAPPER_STD fprintf(stderr,"+++ WARNING: message will be truncated\n");
2352 0 : }
2353 : public:
2354 0 : __PLUMED_WRAPPER_CXX_EXPLICIT add_buffer_to(const char * msg) __PLUMED_WRAPPER_CXX_NOEXCEPT {
2355 0 : init(msg);
2356 : }
2357 0 : add_buffer_to(const T& base,const char * msg) __PLUMED_WRAPPER_CXX_NOEXCEPT:
2358 0 : T(base)
2359 : {
2360 0 : init(msg);
2361 0 : }
2362 0 : add_buffer_to(const add_buffer_to & other) __PLUMED_WRAPPER_CXX_NOEXCEPT:
2363 0 : T(other)
2364 : {
2365 0 : init(other.msg);
2366 0 : }
2367 : add_buffer_to & operator=(const add_buffer_to & other) __PLUMED_WRAPPER_CXX_NOEXCEPT {
2368 : if(this==&other) return *this;
2369 : init(other.msg);
2370 : return *this;
2371 : }
2372 0 : const char* what() const __PLUMED_WRAPPER_CXX_NOEXCEPT __PLUMED_WRAPPER_CXX_OVERRIDE {
2373 0 : return msg;
2374 : }
2375 : #if ! (__cplusplus > 199711L)
2376 : /* Destructor should be declared in order to have the correct throw() before C++11 */
2377 : /* see https://stackoverflow.com/questions/50025862/why-is-the-stdexception-destructor-not-noexcept */
2378 : ~add_buffer_to() throw() {}
2379 : #endif
2380 : };
2381 :
2382 : private:
2383 : /// Small class that wraps plumed_safeptr in order to make its initialization easier
2384 : class SafePtr {
2385 : /// non copyable (copy would require managing buffer, could be added in the future if needed)
2386 : SafePtr(const SafePtr&);
2387 : /// non assignable (assignment would require managing buffer, could be added in the future if needed)
2388 : SafePtr& operator=(SafePtr const&);
2389 : public:
2390 : plumed_safeptr safe;
2391 : /// This buffer holds a copy of the data when they are passed by value.
2392 : /// The size is sufficient to hold any primitive type.
2393 : /// Notice that the buffer is required to enable conversions (e.g., passing a class that can be converted to int)
2394 : /// and, at the same time, allow the object to exist after SafePtr constructor has completed.
2395 : /// A perhaps cleaner implementation would require a base class containing
2396 : /// the plumed_safeptr object, derived classes depending on the
2397 : /// argument type as a template parameter, and overloaded functions
2398 : /// returning this derived class.
2399 : char buffer[32];
2400 : /// Default constructor, nullptr
2401 : SafePtr() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2402 : safe.ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
2403 : safe.nelem=0;
2404 : safe.shape=__PLUMED_WRAPPER_CXX_NULLPTR;
2405 : safe.flags=0x10000*2;
2406 : safe.opt=__PLUMED_WRAPPER_CXX_NULLPTR;
2407 : buffer[0]='\0';
2408 : }
2409 :
2410 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 {
2411 222 : this->safe=safe;
2412 222 : buffer[0]='\0';
2413 : if(nelem>0) this->safe.nelem=nelem;
2414 : if(shape) this->safe.shape=const_cast<__PLUMED_WRAPPER_STD size_t*>(shape);
2415 : }
2416 :
2417 : #if __cplusplus > 199711L
2418 : /// Construct from null
2419 : SafePtr(__PLUMED_WRAPPER_STD nullptr_t,__PLUMED_WRAPPER_STD size_t nelem, const __PLUMED_WRAPPER_STD size_t* shape) noexcept {
2420 : safe.ptr=nullptr;
2421 : safe.nelem=0;
2422 : safe.shape=nullptr;
2423 : safe.flags=0x10000*2;
2424 : safe.opt=nullptr;
2425 : buffer[0]='\0';
2426 : (void) nelem;
2427 : (void) shape;
2428 : }
2429 : #endif
2430 :
2431 : /// Macro that generate a constructor with given type and flags
2432 : #define __PLUMED_WRAPPER_SAFEPTR_INNER(type_,flags_) \
2433 : SafePtr(type_*ptr, __PLUMED_WRAPPER_STD size_t nelem, const __PLUMED_WRAPPER_STD size_t* shape) __PLUMED_WRAPPER_CXX_NOEXCEPT { \
2434 : safe.ptr=ptr; \
2435 : safe.nelem=nelem; \
2436 : safe.shape=const_cast<__PLUMED_WRAPPER_STD size_t*>(shape); \
2437 : safe.flags=flags_; \
2438 : safe.opt=__PLUMED_WRAPPER_CXX_NULLPTR; \
2439 : buffer[0]='\0'; \
2440 : }
2441 :
2442 : /// Macro that uses __PLUMED_WRAPPER_SAFEPTR_INNER to generate constructors with
2443 : /// all possible pointer-const combinations
2444 : #define __PLUMED_WRAPPER_SAFEPTR(type,code,size) \
2445 : __PLUMED_WRAPPER_SAFEPTR_INNER(type, size | (0x10000*(code)) | (0x2000000*2)) \
2446 : __PLUMED_WRAPPER_SAFEPTR_INNER(type const, size | (0x10000*(code)) | (0x2000000*3)) \
2447 : __PLUMED_WRAPPER_SAFEPTR_INNER(type*, size | (0x10000*(code)) | (0x2000000*4)) \
2448 : __PLUMED_WRAPPER_SAFEPTR_INNER(type*const, size | (0x10000*(code)) | (0x2000000*5)) \
2449 : __PLUMED_WRAPPER_SAFEPTR_INNER(type const*, size | (0x10000*(code)) | (0x2000000*6)) \
2450 : __PLUMED_WRAPPER_SAFEPTR_INNER(type const*const, size | (0x10000*(code)) | (0x2000000*7))
2451 :
2452 : /// Macro that generates the constructors from empy types (those of which sizeof cannot be computed)
2453 : #define __PLUMED_WRAPPER_SAFEPTR_EMPTY(type,code) __PLUMED_WRAPPER_SAFEPTR(type,code,0)
2454 :
2455 : /// Macro that generates the constructors from sized types (those of which sizeof can be computed).
2456 : /// In addition to generating constructors with all pointer types, it generates a constructor to
2457 : /// allow pass-by-value
2458 : #define __PLUMED_WRAPPER_SAFEPTR_SIZED(type,code) \
2459 : __PLUMED_WRAPPER_SAFEPTR(type,code,sizeof(type)) \
2460 : SafePtr(type val, __PLUMED_WRAPPER_STD size_t nelem, const __PLUMED_WRAPPER_STD size_t* shape) __PLUMED_WRAPPER_CXX_NOEXCEPT { \
2461 : assert(sizeof(type)<=32); \
2462 : (void) nelem; \
2463 : (void) shape; \
2464 : safe.ptr=buffer; \
2465 : safe.nelem=1; \
2466 : safe.shape=__PLUMED_WRAPPER_CXX_NULLPTR; \
2467 : safe.flags=sizeof(type) | (0x10000*(code)) | (0x2000000*1); \
2468 : safe.opt=__PLUMED_WRAPPER_CXX_NULLPTR; \
2469 : __PLUMED_WRAPPER_STD memcpy(buffer,&val,sizeof(type)); \
2470 : }
2471 :
2472 : /// Here we create all the required instances
2473 : /// 1: void
2474 : /// 3: integral
2475 : /// 4: floating
2476 : /// 5: FILE
2477 : /// 0x100: unsigned
2478 352 : __PLUMED_WRAPPER_SAFEPTR_EMPTY(void,1)
2479 5263 : __PLUMED_WRAPPER_SAFEPTR_SIZED(char,(CHAR_MIN==0)*0x100+3)
2480 : __PLUMED_WRAPPER_SAFEPTR_SIZED(unsigned char,3)
2481 : __PLUMED_WRAPPER_SAFEPTR_SIZED(signed char,0x100+3)
2482 : __PLUMED_WRAPPER_SAFEPTR_SIZED(short,3)
2483 : __PLUMED_WRAPPER_SAFEPTR_SIZED(unsigned short,0x100+3)
2484 10526 : __PLUMED_WRAPPER_SAFEPTR_SIZED(int,3)
2485 : __PLUMED_WRAPPER_SAFEPTR_SIZED(unsigned int,0x100+3)
2486 : __PLUMED_WRAPPER_SAFEPTR_SIZED(long,3)
2487 : __PLUMED_WRAPPER_SAFEPTR_SIZED(unsigned long,0x100+3)
2488 : #if __PLUMED_WRAPPER_CXX_LONGLONG
2489 : __PLUMED_WRAPPER_SAFEPTR_SIZED(long long,3)
2490 : __PLUMED_WRAPPER_SAFEPTR_SIZED(unsigned long long,0x100+3)
2491 : #endif
2492 : __PLUMED_WRAPPER_SAFEPTR_SIZED(float,4)
2493 : __PLUMED_WRAPPER_SAFEPTR_SIZED(double,4)
2494 : __PLUMED_WRAPPER_SAFEPTR_SIZED(long double,4)
2495 : __PLUMED_WRAPPER_SAFEPTR_EMPTY(FILE,5)
2496 :
2497 : /// Return the contained plumed_safeptr
2498 : plumed_safeptr get_safeptr() const __PLUMED_WRAPPER_CXX_NOEXCEPT {
2499 16363 : return safe;
2500 : }
2501 :
2502 : };
2503 :
2504 : #if __cplusplus > 199711L
2505 : /// Small structure used to pass elements of a shape initializer_list.
2506 : /// We use simple conversions, without sign checks, which implicitly means that size=-1 is a very large size
2507 : struct SizeLike {
2508 : std::size_t size;
2509 : SizeLike(short unsigned size): size(size) {}
2510 : SizeLike(unsigned size): size(size) {}
2511 : SizeLike(long unsigned size): size(size) {}
2512 : SizeLike(long long unsigned size): size(size) {}
2513 : SizeLike(short size): size(std::size_t(size)) {}
2514 5263 : SizeLike(int size): size(std::size_t(size)) {}
2515 : SizeLike(long int size): size(std::size_t(size)) {}
2516 : SizeLike(long long int size): size(std::size_t(size)) {}
2517 : };
2518 : #endif
2519 :
2520 : public:
2521 :
2522 : /**
2523 : Check if plumed is installed (for runtime binding)
2524 : \return true if plumed is installed, false otherwise
2525 : \note Equivalent to plumed_installed() but returns a bool
2526 : */
2527 : static bool installed() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2528 : return plumed_installed();
2529 : }
2530 : /**
2531 : Check if Plumed object is valid. Available as of PLUMED 2.5
2532 : \return true if plumed is valid, false otherwise
2533 : \note Equivalent to plumed_valid() but returns a bool
2534 : */
2535 : bool valid() const __PLUMED_WRAPPER_CXX_NOEXCEPT {
2536 : return plumed_valid(main);
2537 : }
2538 : #if __cplusplus > 199711L
2539 : /**
2540 : Same as \ref valid(). Available as of PLUMED 2.5.
2541 :
2542 : Allow code such as
2543 : \verbatim
2544 : Plumed p;
2545 : if(!p) raise_error();
2546 : p.cmd("init");
2547 : \endverbatim
2548 :
2549 : In order to avoid ambiguous conversions, this is only allowed when compiling with C++11
2550 : where it is marked as explicit.
2551 : */
2552 : explicit
2553 : operator bool() const __PLUMED_WRAPPER_CXX_NOEXCEPT {
2554 : return plumed_valid(main);
2555 : }
2556 : #endif
2557 :
2558 : /**
2559 : Returns the number of references to this object. Available as of PLUMED 2.5.
2560 : \note Equivalent to plumed_use_count()
2561 : */
2562 : int useCount() const __PLUMED_WRAPPER_CXX_NOEXCEPT {
2563 : return plumed_use_count(main);
2564 : }
2565 :
2566 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
2567 : /**
2568 : Check if global-plumed has been initialized
2569 : \return true if global plumed object (see global()) is initialized (i.e. if gcreate() has been
2570 : called), false otherwise.
2571 : \note Equivalent to plumed_ginitialized() but returns a bool
2572 : */
2573 : static bool ginitialized() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2574 : return plumed_ginitialized();
2575 : }
2576 : /**
2577 : Check if global-plumed is valid
2578 : \return true if global plumed object (see global()) is valid.
2579 : \note Equivalent to plumed_gvalid() but returns a bool
2580 : */
2581 : static bool gvalid() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2582 : return plumed_gvalid();
2583 : }
2584 : /**
2585 : Initialize global-plumed.
2586 : \warning Using the global objects in C++ is not recommended since they are difficult to use in
2587 : an exception safe manner. In particular, one should explicitly catch exceptions to
2588 : properly call gfinalize()
2589 : \note Equivalent to plumed_gcreate()
2590 : */
2591 : static void gcreate() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2592 : plumed_gcreate();
2593 : }
2594 : /**
2595 : Send a command to global-plumed
2596 : \param key The name of the command to be executed
2597 : \note Equivalent to plumed_gcmd()
2598 : */
2599 : static void gcmd(const char*key) {
2600 : global().cmd(key);
2601 : }
2602 :
2603 : #if __cplusplus > 199711L
2604 :
2605 : /**
2606 : Send a command to global-plumed.
2607 : */
2608 : template<typename T>
2609 : static void gcmd(const char*key,T&& val) {
2610 : global().cmd(key,std::forward<T>(val));
2611 : }
2612 :
2613 : /**
2614 : Send a command to global-plumed.
2615 : This version detects passing size or shape as a pointer.
2616 : */
2617 : template<typename T,typename M>
2618 : static void gcmd(const char*key,T* val, M&& more) {
2619 : global().cmd(key,val,std::forward<M>(more));
2620 : }
2621 :
2622 : /**
2623 : Send a command to global-plumed.
2624 : This version detects passing shape as an initializer_list.
2625 : */
2626 : template<typename T>
2627 : static void gcmd(const char*key,T* val, std::initializer_list<SizeLike> shape) {
2628 : global().cmd(key,val,shape);
2629 : }
2630 :
2631 : #else
2632 :
2633 : /**
2634 : Send a command to global-plumed
2635 : \param key The name of the command to be executed
2636 : \param val The argument.
2637 : \note Equivalent to plumed_gcmd()
2638 : */
2639 : template<typename T>
2640 : static void gcmd(const char*key,T val) {
2641 : global().cmd(key,val);
2642 : }
2643 : /**
2644 : Send a command to global-plumed
2645 : \param key The name of the command to be executed
2646 : \param val The argument.
2647 : \param nelem Number of elements in the passed array, for typechecking.
2648 : \note Equivalent to plumed_gcmd()
2649 : */
2650 : template<typename T>
2651 : static void gcmd(const char*key,T* val,__PLUMED_WRAPPER_STD size_t nelem) {
2652 : global().cmd(key,val,nelem);
2653 : }
2654 :
2655 : /**
2656 : Send a command to global-plumed
2657 : \param key The name of the command to be executed
2658 : \param val The argument.
2659 : \param shape The shape of the argument.
2660 : \note Equivalent to plumed_gcmd()
2661 : */
2662 : template<typename T>
2663 : static void gcmd(const char*key,T* val, const __PLUMED_WRAPPER_STD size_t* shape) {
2664 : global().cmd(key,val,shape);
2665 : }
2666 :
2667 : #endif
2668 :
2669 : /**
2670 : Finalize global-plumed
2671 : */
2672 : static void gfinalize() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2673 : plumed_gfinalize();
2674 : }
2675 : /**
2676 : Returns the Plumed global object
2677 :
2678 : Notice that the object is copied, thus increasing the reference counter of the
2679 : global object. In this manner, the global object will survive after a call to
2680 : \ref gfinalize() if the resulting object is still in scope.
2681 :
2682 : \return The Plumed global object
2683 : */
2684 : static Plumed global() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2685 : return Plumed(plumed_global());
2686 : }
2687 : #endif /*}*/
2688 : /**
2689 : Constructor.
2690 :
2691 : Notice that when using runtime binding the constructed object might be
2692 : invalid. One might check it using the \ref valid() method.
2693 :
2694 : \note Performs the same task a plumed_create()
2695 : */
2696 5263 : Plumed()__PLUMED_WRAPPER_CXX_NOEXCEPT :
2697 : #if __PLUMED_WRAPPER_CXX_DEFAULT_INVALID
2698 : main(plumed_create_invalid())
2699 : #else
2700 5263 : main(plumed_create())
2701 : #endif
2702 : {
2703 : }
2704 :
2705 : /**
2706 : Clone a Plumed object from a FORTRAN char* handler.
2707 :
2708 : \param c The FORTRAN handler (a char[32]).
2709 :
2710 : The reference counter for the corresponding object will be increased
2711 : to make sure that the object will be available after plumed_f_finalize is called
2712 : if the created object is still in scope.
2713 : */
2714 : __PLUMED_WRAPPER_CXX_EXPLICIT Plumed(const char*c)__PLUMED_WRAPPER_CXX_NOEXCEPT :
2715 : main(plumed_create_reference_f(c))
2716 : {
2717 : }
2718 :
2719 : /**
2720 : Create a reference from a void* pointer. Available as of PLUMED 2.5.
2721 : */
2722 : __PLUMED_WRAPPER_CXX_EXPLICIT Plumed(void*v)__PLUMED_WRAPPER_CXX_NOEXCEPT :
2723 : main(plumed_create_reference_v(v))
2724 : {
2725 : }
2726 :
2727 : /**
2728 : Clone a Plumed object from a C plumed structure
2729 :
2730 : \param p The C plumed structure.
2731 :
2732 : The reference counter for the corresponding object will be increased
2733 : to make sure that the object will be available after plumed_finalize is called
2734 : if the created object is still in scope.
2735 : */
2736 : __PLUMED_WRAPPER_CXX_EXPLICIT Plumed(plumed p)__PLUMED_WRAPPER_CXX_NOEXCEPT :
2737 : main(plumed_create_reference(p))
2738 : {
2739 : }
2740 :
2741 : /** Copy constructor.
2742 :
2743 : Takes a reference, incrementing the reference counter of the corresponding object.
2744 : */
2745 : Plumed(const Plumed& p)__PLUMED_WRAPPER_CXX_NOEXCEPT :
2746 : main(plumed_create_reference(p.main))
2747 : {
2748 : }
2749 :
2750 : /** Assignment operator. Available as of PLUMED 2.5.
2751 :
2752 : Takes a reference,incrementing the reference counter of the corresponding object.
2753 : */
2754 : Plumed&operator=(const Plumed&p) __PLUMED_WRAPPER_CXX_NOEXCEPT {
2755 : if(this != &p) {
2756 : // the check is needed to avoid calling plumed_finalize on moved objects
2757 : if(main.p) plumed_finalize(main);
2758 : main=plumed_create_reference(p.main);
2759 : }
2760 : return *this;
2761 : }
2762 :
2763 : /*
2764 : PLUMED >= 2.4 requires a C++11 compiler.
2765 : Anyway, since Plumed.h file might be redistributed with other codes
2766 : and it should be possible to combine it with earlier PLUMED versions,
2767 : we here explicitly check if C+11 is available before enabling move semantics.
2768 : */
2769 : #if __cplusplus > 199711L
2770 : /** Move constructor. Available as of PLUMED 2.5.
2771 : Only if move semantics is enabled.
2772 : */
2773 : Plumed(Plumed&&p)__PLUMED_WRAPPER_CXX_NOEXCEPT :
2774 : main(p.main)
2775 : {
2776 : p.main.p=nullptr;
2777 : }
2778 : /** Move assignment. Available as of PLUMED 2.5.
2779 : Only if move semantics is enabled.
2780 : */
2781 : Plumed& operator=(Plumed&&p)__PLUMED_WRAPPER_CXX_NOEXCEPT {
2782 : if(this != &p) {
2783 : // the check is needed to avoid calling plumed_finalize on moved objects
2784 : if(main.p) plumed_finalize(main);
2785 : main=p.main;
2786 : p.main.p=nullptr;
2787 : }
2788 : return *this;
2789 : }
2790 : #endif
2791 : /**
2792 : Create a PLUMED object loading a specific kernel. Available as of PLUMED 2.5.
2793 :
2794 : It returns an object created with \ref plumed_create_dlopen. The object is owned and
2795 : is then finalized in the destructor. It can be used as follows:
2796 : \verbatim
2797 : PLMD::Plumed p = PLMD::Plumed::dlopen("/path/to/libplumedKernel.so");
2798 : // or, equivalenty:
2799 : // PLMD::Plumed p(PLMD::Plumed::dlopen("/path/to/libplumedKernel.so"));
2800 : p.cmd("init");
2801 : \endverbatim
2802 : or, equivalently, as
2803 : \verbatim
2804 : auto p = PLMD::Plumed::dlopen("/path/to/libplumedKernel.so");
2805 : p.cmd("init");
2806 : \endverbatim
2807 : */
2808 : static Plumed dlopen(const char* path)__PLUMED_WRAPPER_CXX_NOEXCEPT {
2809 : plumed p=plumed_create_dlopen(path);
2810 : Plumed pp(p);
2811 : plumed_finalize(p);
2812 : return pp;
2813 : }
2814 :
2815 : /**
2816 : Create a PLUMED object loading a specific kernel. Available as of PLUMED 2.5.
2817 :
2818 : Same as \ref dlopen(const char* path), but allows a dlopen mode to be chosen explicitly.
2819 : */
2820 : static Plumed dlopen(const char* path,int mode)__PLUMED_WRAPPER_CXX_NOEXCEPT {
2821 : plumed p=plumed_create_dlopen2(path,mode);
2822 : Plumed pp(p);
2823 : plumed_finalize(p);
2824 : return pp;
2825 : }
2826 : /**
2827 : Create a PLUMED object loading from an already opened shared library. Available as of PLUMED 2.8.
2828 :
2829 : Same as \ref dlopen(const char* path), but searches functions in an already loaded library.
2830 : See \ref plumed_create_dlsym.
2831 : */
2832 : static Plumed dlsym(void* dlhandle)__PLUMED_WRAPPER_CXX_NOEXCEPT {
2833 : plumed p=plumed_create_dlsym(dlhandle);
2834 : Plumed pp(p);
2835 : plumed_finalize(p);
2836 : return pp;
2837 : }
2838 :
2839 : /** Invalid constructor. Available as of PLUMED 2.5.
2840 :
2841 : Can be used to initialize an invalid object. It might be useful to postpone
2842 : the initialization of a Plumed object. Consider the following case
2843 : \verbatim
2844 : Plumed p;
2845 : setenv("PLUMED_KERNEL","/path/to/kernel/libplumedKernel.so",1);
2846 : p.cmd("init")
2847 : \endverbatim
2848 : Here the `p` object will be initialized *before* the `PLUMED_KERNEL` env var has been set.
2849 : This can be particularly problematic if `p` is stored in some high level class.
2850 : The following case would do the job
2851 : \verbatim
2852 : Plumed p;
2853 : setenv("PLUMED_KERNEL","/path/to/kernel/libplumedKernel.so",1);
2854 : p=Plumed();
2855 : p.cmd("init")
2856 : \endverbatim
2857 : However, there will be some error reported related to the attempt to load the kernel
2858 : when `p` is initialized. The following solution is the optimal one:
2859 : \verbatim
2860 : Plumed p(Plumed::makeInvalid());
2861 : setenv("PLUMED_KERNEL","/path/to/kernel/libplumedKernel.so",1);
2862 : p=Plumed();
2863 : p.cmd("init")
2864 : \endverbatim
2865 : */
2866 : static Plumed makeInvalid() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2867 : plumed p=plumed_create_invalid();
2868 : Plumed pp(p);
2869 : plumed_finalize(p);
2870 : return pp;
2871 : }
2872 :
2873 : /**
2874 : Create a valid PLMD::Plumed object.
2875 :
2876 : Can be used to create a valid object e.g. when Plumed.h was compiled with
2877 : `-D__PLUMED_WRAPPER_CXX_DEFAULT_INVALID`. For internal usage.
2878 : */
2879 :
2880 : static Plumed makeValid()__PLUMED_WRAPPER_CXX_NOEXCEPT {
2881 : plumed p=plumed_create();
2882 : Plumed pp(p);
2883 : plumed_finalize(p);
2884 : return pp;
2885 : }
2886 :
2887 :
2888 : /**
2889 : Retrieve the C plumed structure for this object.
2890 :
2891 : Notice that the resulting plumed structure is a weak reference and
2892 : should NOT be finalized, unless a new reference is explicitly added
2893 : \verbatim
2894 : Plumed p;
2895 : plumed c=p;
2896 : plumed_finalize(c); // <- this is wrong
2897 : \endverbatim
2898 : \verbatim
2899 : Plumed p;
2900 : plumed c=plumed_create_reference(p);
2901 : plumed_finalize(c); // <- this is right
2902 : \endverbatim
2903 : */
2904 : operator plumed()const __PLUMED_WRAPPER_CXX_NOEXCEPT {
2905 : return main;
2906 : }
2907 :
2908 : /**
2909 : Retrieve a FORTRAN handler for this object
2910 : \param c The FORTRAN handler (a char[32]).
2911 : Notice that the resulting plumed structure is a weak reference and
2912 : should NOT be finalized, unless a new reference is explicitly added.
2913 : */
2914 : void toFortran(char*c)const __PLUMED_WRAPPER_CXX_NOEXCEPT {
2915 : plumed_c2f(main,c);
2916 : }
2917 :
2918 : /**
2919 : Retrieve a void* handler for this object. Available as of PLUMED 2.5.
2920 : Notice that the resulting plumed structure is a weak reference and
2921 : should NOT be finalized, unless a new reference is explicitly added.
2922 : */
2923 : void* toVoid()const __PLUMED_WRAPPER_CXX_NOEXCEPT {
2924 : return plumed_c2v(main);
2925 : }
2926 :
2927 : /**
2928 : Increase reference counter. Available as of PLUMED 2.5.
2929 :
2930 : Using this method improperly might interfere with correct object construction
2931 : and destruction.
2932 : If you want to play with this, also try to compile using `-D__PLUMED_WRAPPER_DEBUG_REFCOUNT=1` and see what happens.
2933 :
2934 : A possible usage is to transfer the ownership of a temporary
2935 : object when it is converted
2936 : \verbatim
2937 : plumed p=Plumed::dlopen(path).incref()
2938 : // without incref(), the just constructed object will be destroyed
2939 : // when the temporary object is deleted.
2940 : ... do stuff ...
2941 : plumed_finalize(p);
2942 : \endverbatim
2943 :
2944 : */
2945 : Plumed& incref() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2946 : plumed_create_reference(main);
2947 : return *this;
2948 : }
2949 :
2950 : /**
2951 : Decrease reference counter. Available as of PLUMED 2.5.
2952 :
2953 : Using this method improperly might interfere with correct object construction
2954 : and destruction.
2955 : If you want to play with this, also try to compile using `-D__PLUMED_WRAPPER_DEBUG_REFCOUNT=1` and see what happens.
2956 : */
2957 : Plumed& decref() __PLUMED_WRAPPER_CXX_NOEXCEPT {
2958 : // calling decref on a moved plumed object should give an error, so we do not check if main.p!=NULL here:
2959 : plumed_finalize(main);
2960 : return *this;
2961 : }
2962 :
2963 : private:
2964 :
2965 : /**
2966 : Private version of cmd. It is used here to avoid duplication of code between typesafe and not-typesafe versions
2967 : */
2968 16363 : static void cmd_priv(plumed main,const char*key, SafePtr& safe, plumed_error*error=__PLUMED_WRAPPER_CXX_NULLPTR) {
2969 :
2970 : plumed_error error_cxx;
2971 : plumed_error_init(&error_cxx);
2972 :
2973 : plumed_nothrow_handler nothrow;
2974 16363 : if(error) {
2975 : plumed_error_init(error);
2976 0 : nothrow.ptr=error;
2977 : } else {
2978 16363 : nothrow.ptr=&error_cxx;
2979 : }
2980 16363 : nothrow.handler=plumed_error_set;
2981 :
2982 : try {
2983 16363 : plumed_cmd_safe_nothrow(main,key,safe.get_safeptr(),nothrow);
2984 0 : } catch (...) {
2985 : assert(error_cxx.code==0); /* no need to plumed_error_finalize here */
2986 : /*
2987 : When loading a kernel <=2.4, plumed_cmd_nothrow could throw an exception.
2988 : If the exception is transmitted through the C interface and arrives here,
2989 : we translate it so as to free the virtual tables of the loaded kernel.
2990 : */
2991 0 : rethrow();
2992 0 : }
2993 : /* plumed_error_rethrow is finalizing */
2994 16363 : if(!error && error_cxx.code!=0) plumed_error_rethrow_cxx(error_cxx);
2995 16363 : }
2996 :
2997 : public:
2998 :
2999 : #if __cplusplus > 199711L
3000 :
3001 : private:
3002 :
3003 : // Small class to manage termination of string_view.
3004 : // The class has a SSO with size 128, so that most messages should fit without
3005 : // any allocation
3006 : class CString {
3007 : /// local buffer (fast)
3008 : char static_buffer[128];
3009 : /// dynamic buffer (requires allocation)
3010 : std::unique_ptr<char[]> dynamic_buffer;
3011 : /// actual pointer
3012 : const char * str;
3013 : /// Move constructor is deleted
3014 : CString(CString&&) = delete;
3015 : /// Move assignment operator is deleted
3016 : CString& operator=(CString&&) = delete;
3017 : public:
3018 : /// Initialize from a const char*, copying the address
3019 : CString(const char* str) noexcept
3020 : {
3021 : this->str=str;
3022 : this->static_buffer[0]='\0';
3023 : }
3024 : /// Initialize from a std:string, taking the address of the corresponding c_str
3025 : CString(const std::string & str) noexcept
3026 : {
3027 : this->str=str.c_str();
3028 : this->static_buffer[0]='\0';
3029 : }
3030 : #if __cplusplus >= 201703L
3031 : /// Initialize from a std::string_view, only C++17
3032 : /// Add a null terminator. If possible, use a local buffer, other wise allocate one.
3033 : CString(std::string_view str) {
3034 : std::size_t len=str.length();
3035 : char* buffer;
3036 : if(sizeof(static_buffer)>=len+1) {
3037 : // in this case, the string_view fits in the local buffer
3038 : buffer=static_buffer;
3039 : } else {
3040 : // in this case, the string_view does not fit in the local buffer
3041 : // hence we allocate a unique_ptr
3042 : dynamic_buffer=std::make_unique<char[]>(len+1);
3043 : buffer=dynamic_buffer.get();
3044 : }
3045 : // at this point, buffer is guaranteed to have size >= len+1
3046 : str.copy(buffer,len);
3047 : buffer[len]='\0'; // ensure null termination
3048 : this->str=buffer;
3049 : this->static_buffer[0]='\0';
3050 : }
3051 : #endif
3052 : operator const char* () const noexcept {
3053 : return str;
3054 : }
3055 : };
3056 :
3057 : /// Internal tool to convert initializer_list to shape
3058 : /// This is just taking an initializer list and making a std::array
3059 5263 : std::array<std::size_t,5> make_shape(std::initializer_list<SizeLike> shape) {
3060 5263 : if(shape.size()>4) throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3061 : std::array<std::size_t,5> shape_;
3062 : unsigned j=0;
3063 10526 : for(auto i : shape) {
3064 5263 : shape_[j]=i.size;
3065 5263 : j++;
3066 : }
3067 5263 : shape_[j]=0;
3068 5263 : return shape_;
3069 : }
3070 :
3071 : /// Internal utility to append a shape.
3072 : /// Create a new shape where newindex has been appended to the last non zero element.
3073 : std::array<std::size_t,5> append_size(std::size_t* shape,std::size_t newindex) {
3074 : std::array<std::size_t,5> shape_;
3075 : unsigned i;
3076 : for(i=0; i<4; i++) {
3077 : shape_[i]=shape[i];
3078 : if(shape[i]==0) break;
3079 : } // one less because we need to append another number!
3080 : if(i==4) throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3081 : shape_[i]=newindex;
3082 : shape_[i+1]=0;
3083 : return shape_;
3084 : }
3085 :
3086 : /// Helper functions for interpreting commands. **They are all internals**.
3087 : /// cmd_helper is called when we have no shape information associated.
3088 : /// cmd_helper_with_shape is called when we have shape information associated.
3089 : /// cmd_helper_with_nelem is called when we have size information associated.
3090 : /// The nocopy bool tells us if this pointer is pointing to a temporary variable, it is propagated by the cmd_helper_with_shape version
3091 : /// It makes sure PLUMED will not keep a copy.
3092 : /// The variants below change for the type of the val argument
3093 : /// There is a chain of SFINAE conditions. This would be better implement with if constexpr, but we avoid doing so
3094 : /// to keep this compatible with C++11.
3095 :
3096 : /// cmd_helper with custom array val (includes std::array)
3097 : /// temporaries are detected and the information is propragated
3098 : template<typename Key,typename T, typename std::enable_if<wrapper::is_custom_array<typename std::remove_reference<T>::type>::value, int>::type = 0>
3099 : void cmd_helper(Key && key,T&& val) {
3100 : std::size_t shape[] { wrapper::custom_array_size<T>(), 0 };
3101 : cmd_helper_with_shape(std::forward<Key>(key),wrapper::custom_array_cast(&val),shape, std::is_rvalue_reference<T&&>::value);
3102 : }
3103 :
3104 : /// cmd_helper with size/data val (typically, std::vector, std::string, small_vector, etc)
3105 : /// temporaries are detected and the information is propragated
3106 : 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>
3107 : void cmd_helper(Key && key,T&& val) {
3108 : std::size_t shape[] { wrapper::size(val), 0 };
3109 : cmd_helper_with_shape(std::forward<Key>(key),val.data(),shape, std::is_rvalue_reference<T&&>::value);
3110 : }
3111 :
3112 : /// cmd_helper with raw pointer val
3113 : /// 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)
3114 : /// here we use std::remove_reference to detect properly pointers to arrays
3115 : 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>
3116 10878 : void cmd_helper(Key && key,T&& val) {
3117 : #if __PLUMED_WRAPPER_CXX_DETECT_SHAPES_STRICT
3118 : // this would be strict checking
3119 : // "a pointer without a specified size is meant to be pointing to a size 1 object"
3120 : std::size_t shape[] { 0, 0 };
3121 : if(val) shape[0]=1;
3122 : cmd_helper_with_shape(std::forward<Key>(key),val,shape);
3123 : #else
3124 : if(wrapper::is_custom_array<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value) {
3125 : // if we are passing a pointer to a fixed sized array, we make sure to retain the information related to
3126 : // the rank of the array and the following (fixed) dimensions
3127 : std::size_t shape[] { 0, 0 };
3128 : if(val) shape[0]=std::numeric_limits<std::size_t>::max();
3129 : cmd_helper_with_shape(std::forward<Key>(key),val,shape);
3130 : } else {
3131 : // otherwise, for backward compatibility, the pointer is assumed with no shape information
3132 10878 : SafePtr s(val,0,nullptr);
3133 10878 : cmd_priv(main,CString(key),s);
3134 : }
3135 : #endif
3136 10878 : }
3137 :
3138 : /// cmd_helper in remaining cases, that is when val is passed by value
3139 : /// temporaries are not detected. However, the argument is passed by value and its address is not copyable anyway
3140 : 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>
3141 : void cmd_helper(Key && key,T&& val) {
3142 : SafePtr s(val,0,nullptr);
3143 : cmd_priv(main,CString(key),s);
3144 : }
3145 :
3146 : /// cmd_helper_with_shape with custom array val (includes std::array and C arrays)
3147 : /// nocopy information is propagated
3148 : template<typename Key,typename T, typename std::enable_if<wrapper::is_custom_array<T>::value, int>::type = 0>
3149 : void cmd_helper_with_shape(Key && key,T* val, __PLUMED_WRAPPER_STD size_t* shape,bool nocopy=false) {
3150 : auto newptr=wrapper::custom_array_cast(val);
3151 : auto newshape=append_size(shape,wrapper::custom_array_size<T>());
3152 : cmd_helper_with_shape(std::forward<Key>(key),newptr,newshape.data(),nocopy);
3153 : }
3154 :
3155 : /// cmd_helper_with_shape with pointer to simple type val.
3156 : /// nocopy information is used to pass the proper flags to plumed
3157 : template<typename Key,typename T, typename std::enable_if<!wrapper::is_custom_array<T>::value, int>::type = 0>
3158 5263 : void cmd_helper_with_shape(Key && key,T* val, __PLUMED_WRAPPER_STD size_t* shape,bool nocopy=false) {
3159 : SafePtr s(val,0,shape);
3160 5263 : if(nocopy) s.safe.flags |= 0x10000000;
3161 5263 : cmd_priv(main,CString(key),s);
3162 5263 : }
3163 :
3164 : #if ! __PLUMED_WRAPPER_CXX_DETECT_SHAPES_STRICT
3165 : /// cmd_helper_with_nelem with custom array val (includes std::array)
3166 : /// this helper is only used for backward compatibility, so it does not need to take into account
3167 : /// the copyability of the pointer
3168 : template<typename Key,typename T, typename std::enable_if<wrapper::is_custom_array<T>::value, int>::type = 0>
3169 : void cmd_with_nelem(Key && key,T* val, __PLUMED_WRAPPER_STD size_t nelem) {
3170 : std::size_t shape[] { 0, 0 };
3171 : if(val) shape[0]=nelem;
3172 : cmd_helper_with_shape(std::forward<Key>(key),val,shape);
3173 : }
3174 :
3175 : /// cmd_helper_with_nelem with pointer to simple type val.
3176 : /// this helper is only used for backward compatibility, so it does not need to take into account
3177 : /// the copyability of the pointer
3178 : template<typename Key,typename T, typename std::enable_if<!wrapper::is_custom_array<T>::value, int>::type = 0>
3179 : void cmd_with_nelem(Key && key,T* val, __PLUMED_WRAPPER_STD size_t nelem) {
3180 : // pointer, directly managed by SafePtr
3181 : SafePtr s(val,nelem,nullptr);
3182 : cmd_priv(main,CString(key),s);
3183 : }
3184 : #endif
3185 :
3186 : public:
3187 :
3188 : /**
3189 : Send a command to this plumed object
3190 : \param key The name of the command to be executed
3191 : \note Similar to \ref plumed_cmd(). It actually called \ref plumed_cmd_nothrow() and
3192 : rethrow any exception raised within PLUMED.
3193 : */
3194 : template<typename Key>
3195 : void cmd(Key && key) {
3196 : SafePtr s;
3197 : cmd_priv(main,CString(key),s);
3198 : }
3199 :
3200 : /**
3201 : Send a command to this plumed object
3202 : \param key The name of the command to be executed
3203 : \param val The argument.
3204 : */
3205 : template<typename Key,typename T>
3206 : void cmd(Key && key,T&& val) {
3207 10878 : cmd_helper(std::forward<Key>(key),std::forward<T>(val));
3208 10878 : }
3209 :
3210 : /**
3211 : Send a command to this plumed object
3212 : \param key The name of the command to be executed
3213 : \param val The argument.
3214 : \note This overload accepts a pointer and corresponding size
3215 : information. It's usage is discouraged:
3216 : the overload accepting shape information should be preferred.
3217 : */
3218 :
3219 : template<typename Key,typename T, typename I, typename std::enable_if<std::is_integral<I>::value, int>::type = 0>
3220 : void cmd(Key && key,T* val, I nelem) {
3221 : #if __PLUMED_WRAPPER_CXX_DETECT_SHAPES_STRICT
3222 : static_assert("in strict mode you cannot pass nelem, please pass full shape instead");
3223 : #else
3224 : cmd_with_nelem(std::forward<Key>(key),val,__PLUMED_WRAPPER_STD size_t(nelem));
3225 : #endif
3226 : }
3227 :
3228 : /**
3229 : Send a command to this plumed object
3230 : \param key The name of the command to be executed
3231 : \param val The argument.
3232 : \note This overload accepts a pointer and corresponding shape
3233 : information. Shape is passed a size_t pointer,
3234 : but the overload accepting an initializer_list
3235 : has a more friendly syntax.
3236 : */
3237 : template<typename Key,typename T>
3238 : void cmd(Key && key,T* val, __PLUMED_WRAPPER_STD size_t* shape) {
3239 : unsigned i;
3240 : for(i=0; i<5; i++) if(shape[i]==0) break;
3241 : if(i==5) throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3242 : cmd_helper_with_shape(std::forward<Key>(key),val,shape);
3243 : }
3244 :
3245 : /**
3246 : Send a command to this plumed object
3247 : \param key The name of the command to be executed
3248 : \param val The argument.
3249 : \note This overload accepts a pointer and corresponding shape
3250 : information. Shape is passed a size_t pointer,
3251 : but the overload accepting an initializer_list
3252 : has a more friendly syntax.
3253 : */
3254 : template<typename Key,typename T>
3255 5263 : void cmd(Key && key,T* val, std::initializer_list<SizeLike> shape) {
3256 5263 : auto shape_=make_shape(shape);
3257 5263 : cmd_helper_with_shape(std::forward<Key>(key),val,shape_.data());
3258 5263 : }
3259 :
3260 : public:
3261 :
3262 : #else
3263 :
3264 : /**
3265 : Send a command to this plumed object
3266 : \param key The name of the command to be executed
3267 : \note Similar to \ref plumed_cmd(). It actually called \ref plumed_cmd_nothrow() and
3268 : rethrow any exception raised within PLUMED.
3269 : */
3270 : void cmd(const char*key) {
3271 : plumed_cmd_cxx(main,key);
3272 : }
3273 :
3274 :
3275 : /**
3276 : Send a command to this plumed object
3277 : \param key The name of the command to be executed
3278 : \param val The argument, passed by value.
3279 : \note Similar to \ref plumed_cmd(). It actually called \ref plumed_cmd_nothrow() and
3280 : rethrow any exception raised within PLUMED.
3281 : \note Unless PLUMED library is <=2.7,
3282 : the type of the argument is checked.
3283 : */
3284 : template<typename T>
3285 : void cmd(const char*key,T val) {
3286 : plumed_cmd_cxx(main,key,val);
3287 : }
3288 :
3289 : /**
3290 : Send a command to this plumed object
3291 : \param key The name of the command to be executed
3292 : \param val The argument, passed by pointer.
3293 : \param shape A zero-terminated array containing the shape of the data.
3294 : \note Similar to \ref plumed_cmd(). It actually called \ref plumed_cmd_nothrow() and
3295 : rethrow any exception raised within PLUMED.
3296 : \note Unless PLUMED library is <=2.7,
3297 : the type of the argument is checked. If shape is passed, it is also
3298 : checked that PLUMED access only compatible indexes.
3299 : */
3300 : template<typename T>
3301 : void cmd(const char*key,T* val, const __PLUMED_WRAPPER_STD size_t* shape) {
3302 : unsigned i;
3303 : for(i=0; i<5; i++) if(shape[i]==0) break;
3304 : if(i==5) throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3305 : plumed_cmd_cxx(main,key,val,shape);
3306 : }
3307 :
3308 : /**
3309 : Send a command to this plumed object
3310 : \param key The name of the command to be executed
3311 : \param val The argument, passed by pointer.
3312 : \param nelem The number of elements passed.
3313 : \note Similar to \ref plumed_cmd(). It actually called \ref plumed_cmd_nothrow() and
3314 : rethrow any exception raised within PLUMED.
3315 : \note Unless PLUMED library is <=2.7,
3316 : the type of the argument is checked. nelem is used to check
3317 : the maximum index interpreting the array as flattened.
3318 : */
3319 : template<typename T>
3320 : void cmd(const char*key,T* val, __PLUMED_WRAPPER_STD size_t nelem) {
3321 : plumed_cmd_cxx(main,key,val,nelem);
3322 : }
3323 :
3324 : #endif
3325 :
3326 :
3327 : /**
3328 : Destructor
3329 :
3330 : It calls \ref plumed_finalize(). Notice that this is done also if the
3331 : constructor failed (that is, if it returned an invalid object). This allows
3332 : declaring Plumed objects also if PLUMED is actually not available, provided
3333 : one does not use the \ref cmd method.
3334 :
3335 : Destructor is virtual so as to allow correct inheritance from Plumed object.
3336 : */
3337 : #if __PLUMED_WRAPPER_CXX_POLYMORPHIC
3338 : virtual
3339 : #endif
3340 5263 : ~Plumed() __PLUMED_WRAPPER_CXX_NOEXCEPT {
3341 : // the check is needed to avoid calling plumed_finalize on moved objects
3342 5263 : if(main.p) plumed_finalize(main);
3343 5263 : }
3344 :
3345 : /**
3346 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3347 : namely implement typechecks and rethrowing exception.
3348 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3349 : They are also used by the Plumed::cmd functions to avoid code duplication.
3350 : Available as of PLUMED 2.8.
3351 : */
3352 : static void plumed_cmd_cxx(plumed p,const char*key,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3353 : SafePtr s;
3354 : cmd_priv(p,key,s,error);
3355 : }
3356 :
3357 : /**
3358 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3359 : namely implement typechecks and rethrowing exception.
3360 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3361 : They are also used by the Plumed::cmd functions to avoid code duplication.
3362 : Available as of PLUMED 2.8.
3363 : */
3364 : template<typename T>
3365 222 : static void plumed_cmd_cxx(plumed p,const char*key,T val,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3366 : SafePtr s(val,0,__PLUMED_WRAPPER_CXX_NULLPTR);
3367 222 : cmd_priv(p,key,s,error);
3368 222 : }
3369 :
3370 : /**
3371 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3372 : namely implement typechecks and rethrowing exception.
3373 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3374 : They are also used by the Plumed::cmd functions to avoid code duplication.
3375 : Available as of PLUMED 2.8.
3376 : */
3377 : template<typename T>
3378 : static void plumed_cmd_cxx(plumed p,const char*key,T* val,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3379 : SafePtr s(val,0,__PLUMED_WRAPPER_CXX_NULLPTR);
3380 : cmd_priv(p,key,s,error);
3381 : }
3382 :
3383 : /**
3384 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3385 : namely implement typechecks and rethrowing exception.
3386 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3387 : They are also used by the Plumed::cmd functions to avoid code duplication.
3388 : Available as of PLUMED 2.8.
3389 : */
3390 : template<typename T>
3391 : 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) {
3392 : SafePtr s(val,nelem,__PLUMED_WRAPPER_CXX_NULLPTR);
3393 : cmd_priv(p,key,s,error);
3394 : }
3395 :
3396 : /**
3397 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3398 : namely implement typechecks and rethrowing exception.
3399 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3400 : They are also used by the Plumed::cmd functions to avoid code duplication.
3401 : Available as of PLUMED 2.8.
3402 : */
3403 : template<typename T>
3404 : 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) {
3405 : unsigned i;
3406 : for(i=0; i<5; i++) if(shape[i]==0) break;
3407 : if(i==5) throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3408 : SafePtr s(val,0,shape);
3409 : cmd_priv(p,key,s,error);
3410 : }
3411 :
3412 :
3413 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
3414 : /**
3415 : \related Plumed
3416 : This function can be used to make plumed_gcmd behave as the C++ wrapper PLMD::Plumed::gcmd,
3417 : namely implement typechecks and rethrowing exception.
3418 : To be used through the macro plumed_gcmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3419 : Available as of PLUMED 2.8.
3420 : */
3421 :
3422 : /**
3423 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3424 : namely implement typechecks and rethrowing exception.
3425 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3426 : They are also used by the Plumed::cmd functions to avoid code duplication.
3427 : Available as of PLUMED 2.8.
3428 : */
3429 : static void plumed_gcmd_cxx(const char*key,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3430 : plumed_cmd_cxx(plumed_global(),key,error);
3431 : }
3432 :
3433 : /**
3434 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3435 : namely implement typechecks and rethrowing exception.
3436 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3437 : They are also used by the Plumed::cmd functions to avoid code duplication.
3438 : Available as of PLUMED 2.8.
3439 : */
3440 : template<typename T>
3441 : static void plumed_gcmd_cxx(const char*key,T val,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3442 : plumed_cmd_cxx(plumed_global(),key,val,error);
3443 : }
3444 :
3445 : /**
3446 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3447 : namely implement typechecks and rethrowing exception.
3448 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3449 : They are also used by the Plumed::cmd functions to avoid code duplication.
3450 : Available as of PLUMED 2.8.
3451 : */
3452 : template<typename T>
3453 : static void plumed_gcmd_cxx(const char*key,T val, __PLUMED_WRAPPER_STD size_t nelem,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3454 : plumed_cmd_cxx(plumed_global(),key,val,nelem,error);
3455 : }
3456 :
3457 : /**
3458 : These functions can be used to make plumed_cmd behave as the C++ wrapper PLMD::Plumed::cmd,
3459 : namely implement typechecks and rethrowing exception.
3460 : To be used through the macro plumed_cmd (defined when __PLUMED_WRAPPER_CXX_BIND_C==1).
3461 : They are also used by the Plumed::cmd functions to avoid code duplication.
3462 : Available as of PLUMED 2.8.
3463 : */
3464 : template<typename T>
3465 : static void plumed_gcmd_cxx(const char*key,T val, const __PLUMED_WRAPPER_STD size_t* shape,plumed_error* error=__PLUMED_WRAPPER_CXX_NULLPTR) {
3466 : unsigned i;
3467 : for(i=0; i<5; i++) if(shape[i]==0) break;
3468 : if(i==5) throw Plumed::ExceptionTypeError("Maximum shape size is 4");
3469 : plumed_cmd_cxx(plumed_global(),key,val,shape,error);
3470 : }
3471 :
3472 : #endif /*}*/
3473 :
3474 : #if __PLUMED_WRAPPER_CXX_BIND_C /*{*/
3475 :
3476 : #define __PLUMED_WRAPPER_REDEFINE_CMD ::PLMD::Plumed::plumed_cmd_cxx
3477 :
3478 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
3479 : #define __PLUMED_WRAPPER_REDEFINE_GCMD ::PLMD::Plumed::plumed_gcmd_cxx
3480 : #endif /*}*/
3481 :
3482 : #define __PLUMED_WRAPPER_REDEFINE_ERROR_RETHROW ::PLMD::Plumed::plumed_error_rethrow_cxx
3483 :
3484 : #endif /*}*/
3485 :
3486 : };
3487 :
3488 : /**
3489 : \related Plumed
3490 : Comparison operator. Available as of PLUMED 2.5.
3491 : */
3492 : inline
3493 : bool operator==(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3494 : return a.toVoid()==b.toVoid();
3495 : }
3496 :
3497 : /**
3498 : \related Plumed
3499 : Comparison operator. Available as of PLUMED 2.5.
3500 : */
3501 : inline
3502 : bool operator!=(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3503 : return a.toVoid()!=b.toVoid();
3504 : }
3505 :
3506 : /**
3507 : \related Plumed
3508 : Comparison operator. Available as of PLUMED 2.5.
3509 : */
3510 : inline
3511 : bool operator<=(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3512 : return a.toVoid()<=b.toVoid();
3513 : }
3514 :
3515 : /**
3516 : \related Plumed
3517 : Comparison operator. Available as of PLUMED 2.5.
3518 : */
3519 : inline
3520 : bool operator<(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3521 : return a.toVoid()<b.toVoid();
3522 : }
3523 :
3524 : /**
3525 : \related Plumed
3526 : Comparison operator. Available as of PLUMED 2.5.
3527 : */
3528 : inline
3529 : bool operator>=(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3530 : return a.toVoid()>=b.toVoid();
3531 : }
3532 :
3533 : /**
3534 : \related Plumed
3535 : Comparison operator. Available as of PLUMED 2.5.
3536 : */
3537 : inline
3538 : bool operator>(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
3539 : return a.toVoid()>b.toVoid();
3540 : }
3541 :
3542 : __PLUMED_WRAPPER_ANONYMOUS_END /*}*/
3543 :
3544 : }
3545 :
3546 : #endif /*}*/
3547 :
3548 : #endif /*}*/
3549 :
3550 : /* END OF DECLARATIONS */
3551 :
3552 : /*
3553 :
3554 : 1: emit implementation
3555 : 0: do not emit implementation
3556 :
3557 : Allows an implementation to be emitted together with the declarations.
3558 :
3559 : Used to decide if definitions should be emitted. This macro could have a different
3560 : value when Plumed.h is reincluded. As a consequence, we map it to a local
3561 : macro (__PLUMED_WRAPPER_IMPLEMENTATION_) that is reset at the end of this file.
3562 : */
3563 :
3564 : #ifdef __PLUMED_WRAPPER_IMPLEMENTATION
3565 : #define __PLUMED_WRAPPER_IMPLEMENTATION_ __PLUMED_WRAPPER_IMPLEMENTATION
3566 : #else
3567 : #define __PLUMED_WRAPPER_IMPLEMENTATION_ 0
3568 : #endif
3569 :
3570 : /* BEGINNING OF DEFINITIONS */
3571 :
3572 : #if __PLUMED_WRAPPER_IMPLEMENTATION_ /*{*/
3573 : #ifndef __PLUMED_wrapper_Plumed_implementation /*{*/
3574 : #define __PLUMED_wrapper_Plumed_implementation
3575 :
3576 : /*
3577 : the following macros only control the implementation
3578 : */
3579 :
3580 : /*
3581 : 1: enable the definition of plumed_symbol_table_reexport
3582 : 0: does not enable the definition of plumed_symbol_table_reexport
3583 :
3584 : This is only needed in the official plumed library to make
3585 : the symbol table available. This is a hack to reexport the function table
3586 : and is only needed when creating the library libplumed.so.
3587 : */
3588 :
3589 : #ifndef __PLUMED_WRAPPER_REEXPORT_SYMBOL_TABLE
3590 : #define __PLUMED_WRAPPER_REEXPORT_SYMBOL_TABLE 0
3591 : #endif
3592 :
3593 : /*
3594 : 1: write on stderr changes in reference counters
3595 : 0: do not write changes in reference counters
3596 :
3597 : Used for debugging.
3598 :
3599 : Only used in definitions.
3600 : */
3601 :
3602 : #ifndef __PLUMED_WRAPPER_DEBUG_REFCOUNT
3603 : #define __PLUMED_WRAPPER_DEBUG_REFCOUNT 0
3604 : #endif
3605 :
3606 : /*
3607 : 1: emit plumed_kernel_register function (default)
3608 : 0: do not emit plumed_kernel_register function
3609 :
3610 : This function is only needed to avoid an extra warning when loading old (<=2.4) kernels.
3611 : We might change its default in the future.
3612 :
3613 : Used only in definitions.
3614 : */
3615 :
3616 : #ifndef __PLUMED_WRAPPER_KERNEL_REGISTER
3617 : #define __PLUMED_WRAPPER_KERNEL_REGISTER 1
3618 : #endif
3619 :
3620 : /*
3621 : 1: emit Fortran wrappers
3622 : 0: do not emit Fortran wrappers (default)
3623 :
3624 : Used only in definitions.
3625 : */
3626 :
3627 : #ifndef __PLUMED_WRAPPER_FORTRAN
3628 : #define __PLUMED_WRAPPER_FORTRAN 0
3629 : #endif
3630 :
3631 : /*
3632 : With internal interface, it does not make sense to emit kernel register or fortran interfaces
3633 : */
3634 :
3635 : #if ! __PLUMED_WRAPPER_EXTERN /*{*/
3636 : #undef __PLUMED_WRAPPER_KERNEL_REGISTER
3637 : #define __PLUMED_WRAPPER_KERNEL_REGISTER 0
3638 : #undef __PLUMED_WRAPPER_FORTRAN
3639 : #define __PLUMED_WRAPPER_FORTRAN 0
3640 : #endif /*}*/
3641 :
3642 : #ifdef __PLUMED_HAS_DLOPEN
3643 : #include <dlfcn.h> /* dlopen dlerror dlsym */
3644 : #endif
3645 :
3646 : #if __PLUMED_WRAPPER_CXX_STD
3647 : #include <cstdio> /* fprintf */
3648 : #include <cstring> /* memcpy strlen strncpy memcmp memmove strcmp memcpy */
3649 : #include <cassert> /* assert */
3650 : #include <cstdlib> /* getenv malloc free abort */
3651 : #include <climits> /* CHAR_BIT */
3652 : #else
3653 : #include <stdio.h>
3654 : #include <string.h>
3655 : #include <assert.h>
3656 : #include <stdlib.h>
3657 : #include <limits.h>
3658 : #endif
3659 :
3660 : /**
3661 : Function pointer to plumed_create
3662 : */
3663 :
3664 : typedef void*(*plumed_create_pointer)(void);
3665 : /**
3666 : Function pointer to plumed_cmd
3667 : */
3668 : typedef void(*plumed_cmd_pointer)(void*,const char*,const void*);
3669 :
3670 : /**
3671 : Function pointer to plumed_finalize
3672 : */
3673 : typedef void(*plumed_finalize_pointer)(void*);
3674 :
3675 : /**
3676 : Holder for plumedmain function pointers.
3677 : */
3678 : typedef struct {
3679 : plumed_create_pointer create;
3680 : plumed_cmd_pointer cmd;
3681 : plumed_finalize_pointer finalize;
3682 : } plumed_plumedmain_function_holder;
3683 :
3684 : /**
3685 : Holder for plumed symbol table.
3686 :
3687 : The table contains pointers to function exported from plumed. Functions can be added increasing the version number.
3688 : Notice that the default way to extend functionalities is by adding cmd strings. This is a last resort, and all new
3689 : functions should be explicitly motivated. Here's the addition:
3690 :
3691 : version=2, cmd_nothrow.
3692 :
3693 : This function accepts an extra argument `plumed_nothrow_handler*handler`.
3694 : In case an exception is thrown within plumed, it just calls `handler->handler(handler->ptr,code,message,opt)` and return.
3695 : An alternative would have been to install an error handler (with a call to cmd("setErrorHandler")). However, the cost
3696 : of doing it everytime Plumed::cmd is called is too high. On the other hand, installing it only at object construction
3697 : is very risky since and object created in that way would not report any error if manipulated from the C interface.
3698 : So, it looks like this is the only possibility.
3699 :
3700 : version=3, cmd_safe and cmd_safe_nothrow
3701 :
3702 : These are functions that accept a plumed_safeptr object, which can carry information about the passed type and size.
3703 : Since new information should be passed at every cmd call, this can only be obtained by adding new cmd calls.
3704 :
3705 : version=4, thread-safe reference counter
3706 :
3707 : These functions allow to access a thread-safe reference counter that is stored within the PlumedMain object.
3708 : This allows avoiding to enable atomic access also the C compiler used build Plumed.c. It's added here and not as a new
3709 : cmd since this is a very low-level functionality.
3710 : */
3711 : typedef struct {
3712 : /**
3713 : Version number.
3714 :
3715 : Minimum value is 1.
3716 : */
3717 : int version;
3718 : /**
3719 : Pointers to standard plumed functions (create/cmd/finalize).
3720 :
3721 : Always available.
3722 : */
3723 : plumed_plumedmain_function_holder functions;
3724 : /**
3725 : Pointer to a cmd function guaranteed not to throw exceptions.
3726 :
3727 : Available with version>=2.
3728 : */
3729 : void (*cmd_nothrow)(void*plumed,const char*key,const void*val,plumed_nothrow_handler);
3730 : /**
3731 : Pointer to a cmd function that accepts typeinfos.
3732 :
3733 : Available with version>=3.
3734 : */
3735 : void (*cmd_safe)(void*plumed,const char*key,plumed_safeptr);
3736 :
3737 : /**
3738 : Pointer to a cmd function guaranteed not to throw exceptions and that accepts typeinfos.
3739 :
3740 : Available with version>=3.
3741 : */
3742 : void (*cmd_safe_nothrow)(void*plumed,const char*key,plumed_safeptr,plumed_nothrow_handler);
3743 :
3744 : /**
3745 : Pointer to a function that increments the internal reference counter.
3746 :
3747 : Available with version>=4.
3748 : */
3749 : unsigned (*create_reference)(void*);
3750 : /**
3751 : Pointer to a function that decrements the internal reference counter.
3752 :
3753 : Available with version>=4.
3754 : */
3755 : unsigned (*delete_reference)(void*);
3756 : /**
3757 : Pointer to a function that returns the internal reference counter.
3758 :
3759 : Available with version>=4.
3760 : */
3761 : unsigned (*use_count)(void*);
3762 : } plumed_symbol_table_type;
3763 :
3764 : /* Utility to convert function pointers to pointers, just for the sake of printing them */
3765 : #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))); }
3766 :
3767 : #define __PLUMED_GETENV __PLUMED_WRAPPER_STD getenv
3768 : #define __PLUMED_FPRINTF __PLUMED_WRAPPER_STD fprintf
3769 :
3770 : /**
3771 : Historically (PLUMED<=2.4) register for plumedmain function pointers.
3772 : As of PLUMED>=2.5, this function does not do anything except for reporting the attempt to register
3773 : something. It always returns NULL. The function should be here anyway to allow an incomplete
3774 : libplumedKernel (<=2.4), expecting this function to be present, to be loaded correctly.
3775 : */
3776 : #if __PLUMED_WRAPPER_KERNEL_REGISTER
3777 : /* Since it is only called from outside, it must be hardcoded to be extern */
3778 : __PLUMED_WRAPPER_EXTERN_C_BEGIN /*{*/
3779 : extern plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder*);
3780 26 : plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder* f) {
3781 : void* tmpptr;
3782 26 : if(f) {
3783 26 : if(__PLUMED_GETENV("PLUMED_LOAD_DEBUG")) {
3784 0 : __PLUMED_FPRINTF(stderr,"+++ Ignoring registration at %p (",__PLUMED_WRAPPER_STATIC_CAST(const void*,f));
3785 : __PLUMED_CONVERT_FPTR(tmpptr,f->create);
3786 0 : __PLUMED_FPRINTF(stderr,"%p,",tmpptr);
3787 : __PLUMED_CONVERT_FPTR(tmpptr,f->cmd);
3788 0 : __PLUMED_FPRINTF(stderr,"%p,",tmpptr);
3789 : __PLUMED_CONVERT_FPTR(tmpptr,f->finalize);
3790 0 : __PLUMED_FPRINTF(stderr,"%p) +++\n",tmpptr);
3791 : }
3792 : }
3793 26 : return __PLUMED_WRAPPER_CXX_NULLPTR;
3794 : }
3795 : __PLUMED_WRAPPER_EXTERN_C_END /*}*/
3796 : #endif
3797 :
3798 : #if defined( __PLUMED_HAS_DLOPEN) /*{*/
3799 : /**
3800 : Try to dlopen a path with a given mode.
3801 : If the dlopen command fails, it tries to strip the `Kernel` part of the name.
3802 :
3803 : This function is declared static (internal linkage) so that it is not visible from outside.
3804 : It is first declared then defined to make sure it is a regular C static function.
3805 : */
3806 :
3807 : __PLUMED_WRAPPER_INTERNALS_BEGIN
3808 9 : void* plumed_attempt_dlopen(const char*path,int mode) {
3809 : char* pathcopy;
3810 : void* p;
3811 : char* pc;
3812 : __PLUMED_WRAPPER_STD size_t strlenpath;
3813 : pathcopy=__PLUMED_WRAPPER_CXX_NULLPTR;
3814 : p=__PLUMED_WRAPPER_CXX_NULLPTR;
3815 : pc=__PLUMED_WRAPPER_CXX_NULLPTR;
3816 : strlenpath=0;
3817 9 : dlerror();
3818 9 : p=dlopen(path,mode);
3819 9 : if(!p) {
3820 : /*
3821 : Something went wrong. We try to remove "Kernel" string from the PLUMED_KERNEL variable
3822 : and load directly the shared library. Notice that this particular path is only expected
3823 : to be necessary when using PLUMED<=2.4 and the symbols in the main executable are
3824 : not visible. All the other cases (either PLUMED>=2.5 or symbols in the main executable visible)
3825 : should work correctly without entering here.
3826 : */
3827 0 : __PLUMED_FPRINTF(stderr,"+++ An error occurred. Message from dlopen(): %s +++\n",dlerror());
3828 0 : strlenpath=__PLUMED_WRAPPER_STD strlen(path);
3829 0 : pathcopy=__PLUMED_WRAPPER_STATIC_CAST(char*, plumed_malloc(strlenpath+1));
3830 0 : if(!pathcopy) {
3831 0 : __PLUMED_FPRINTF(stderr,"+++ Allocation error +++\n");
3832 0 : __PLUMED_WRAPPER_STD abort();
3833 : }
3834 : __PLUMED_WRAPPER_STD memcpy(pathcopy,path,strlenpath+1);
3835 0 : pc=pathcopy+strlenpath-6;
3836 0 : while(pc>=pathcopy && __PLUMED_WRAPPER_STD memcmp(pc,"Kernel",6)) pc--;
3837 0 : if(pc>=pathcopy) {
3838 0 : __PLUMED_WRAPPER_STD memmove(pc, pc+6, __PLUMED_WRAPPER_STD strlen(pc)-5);
3839 0 : __PLUMED_FPRINTF(stderr,"+++ This error is expected if you are trying to load a kernel <=2.4\n");
3840 0 : __PLUMED_FPRINTF(stderr,"+++ Trying %s +++\n",pathcopy);
3841 0 : dlerror();
3842 0 : p=dlopen(pathcopy,mode);
3843 0 : if(!p) __PLUMED_FPRINTF(stderr,"+++ An error occurred. Message from dlopen(): %s +++\n",dlerror());
3844 : }
3845 0 : plumed_free(pathcopy);
3846 : }
3847 9 : return p;
3848 : }
3849 : __PLUMED_WRAPPER_INTERNALS_END
3850 :
3851 : /**
3852 : Utility to search for a function.
3853 : */
3854 : #ifdef __cplusplus
3855 : #define __PLUMED_WRAPPER_SEARCHF_CAST(functype,func,tmpptr) func=reinterpret_cast<functype>(tmpptr)
3856 : #else
3857 : #define __PLUMED_WRAPPER_SEARCHF_CAST(functype,func,tmpptr) *(void **)&func=tmpptr
3858 : #endif
3859 : #define __PLUMED_SEARCH_FUNCTION(functype,tmpptr,handle,func,name,debug) \
3860 : if(!func) { \
3861 : tmpptr=dlsym(handle,name); \
3862 : if(tmpptr) { \
3863 : __PLUMED_WRAPPER_SEARCHF_CAST(functype,func,tmpptr); \
3864 : if(debug) __PLUMED_FPRINTF(stderr,"+++ %s found at %p +++\n",name,tmpptr); \
3865 : } else { \
3866 : if(debug) __PLUMED_FPRINTF(stderr,"+++ Function %s not found\n",name); \
3867 : } \
3868 : }
3869 :
3870 : /**
3871 : Search symbols in a dlopened library.
3872 :
3873 : This function is declared static (internal linkage) so that it is not visible from outside.
3874 : */
3875 : __PLUMED_WRAPPER_INTERNALS_BEGIN
3876 9 : void plumed_search_symbols(void* handle, plumed_plumedmain_function_holder* f,plumed_symbol_table_type** table) {
3877 : plumed_plumedmain_function_holder functions;
3878 : plumed_symbol_table_type* table_ptr;
3879 : void* tmpptr;
3880 : char* debug;
3881 : functions.create=__PLUMED_WRAPPER_CXX_NULLPTR;
3882 : functions.cmd=__PLUMED_WRAPPER_CXX_NULLPTR;
3883 : functions.finalize=__PLUMED_WRAPPER_CXX_NULLPTR;
3884 : table_ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
3885 9 : tmpptr=__PLUMED_WRAPPER_CXX_NULLPTR;
3886 : /*
3887 : Notice that as of PLUMED 2.5 we ignore self registrations.
3888 : Pointers are searched in the form of a single pointer to a structure, which
3889 : is the standard way in PLUMED 2.5, as well as using alternative names used in
3890 : PLUMED 2.0 to 2.4 (e.g. plumedmain_create) and in some intermediate versions between
3891 : PLUMED 2.4 and 2.5 (e.g. plumed_plumedmain_create). The last chance is probably
3892 : unnecessary and might be removed at some point.
3893 : */
3894 9 : debug=__PLUMED_GETENV("PLUMED_LOAD_DEBUG");
3895 9 : table_ptr=__PLUMED_WRAPPER_STATIC_CAST(plumed_symbol_table_type*, dlsym(handle,"plumed_symbol_table"));
3896 9 : if(table_ptr) functions=table_ptr->functions;
3897 9 : if(debug) {
3898 0 : if(table_ptr) {
3899 0 : __PLUMED_FPRINTF(stderr,"+++ plumed_symbol_table version %i found at %p +++\n",table_ptr->version,__PLUMED_WRAPPER_STATIC_CAST(void*,table_ptr));
3900 0 : __PLUMED_FPRINTF(stderr,"+++ plumed_function_pointers found at %p (",__PLUMED_WRAPPER_STATIC_CAST(void*,&table_ptr->functions));
3901 : __PLUMED_CONVERT_FPTR(tmpptr,functions.create);
3902 0 : __PLUMED_FPRINTF(stderr,"%p,",tmpptr);
3903 : __PLUMED_CONVERT_FPTR(tmpptr,functions.cmd);
3904 0 : __PLUMED_FPRINTF(stderr,"%p,",tmpptr);
3905 : __PLUMED_CONVERT_FPTR(tmpptr,functions.finalize);
3906 0 : __PLUMED_FPRINTF(stderr,"%p) +++\n",tmpptr);
3907 : } else {
3908 0 : __PLUMED_FPRINTF(stderr,"+++ plumed_symbol_table (available in PLUMED>=2.5) not found, perhaps kernel is older +++\n");
3909 : }
3910 : }
3911 : /* only searches if they were not found already */
3912 9 : __PLUMED_SEARCH_FUNCTION(plumed_create_pointer,tmpptr,handle,functions.create,"plumedmain_create",debug);
3913 9 : __PLUMED_SEARCH_FUNCTION(plumed_create_pointer,tmpptr,handle,functions.create,"plumed_plumedmain_create",debug);
3914 9 : __PLUMED_SEARCH_FUNCTION(plumed_cmd_pointer,tmpptr,handle,functions.cmd,"plumedmain_cmd",debug);
3915 9 : __PLUMED_SEARCH_FUNCTION(plumed_cmd_pointer,tmpptr,handle,functions.cmd,"plumed_plumedmain_cmd",debug);
3916 9 : __PLUMED_SEARCH_FUNCTION(plumed_finalize_pointer,tmpptr,handle,functions.finalize,"plumedmain_finalize",debug);
3917 9 : __PLUMED_SEARCH_FUNCTION(plumed_finalize_pointer,tmpptr,handle,functions.finalize,"plumed_plumedmain_finalize",debug);
3918 9 : if(functions.create && functions.cmd && functions.finalize) {
3919 9 : if(debug) __PLUMED_FPRINTF(stderr,"+++ PLUMED was loaded correctly +++\n");
3920 9 : *f=functions;
3921 9 : if(table) *table=table_ptr;
3922 : } else {
3923 0 : if(!functions.create) __PLUMED_FPRINTF(stderr,"+++ Pointer to (plumed_)plumedmain_create not found +++\n");
3924 0 : if(!functions.cmd) __PLUMED_FPRINTF(stderr,"+++ Pointer to (plumed_)plumedmain_cmd not found +++\n");
3925 0 : if(!functions.finalize) __PLUMED_FPRINTF(stderr,"+++ Pointer to (plumed_)plumedmain_finalize not found +++\n");
3926 0 : f->create=__PLUMED_WRAPPER_CXX_NULLPTR;
3927 0 : f->cmd=__PLUMED_WRAPPER_CXX_NULLPTR;
3928 0 : f->finalize=__PLUMED_WRAPPER_CXX_NULLPTR;
3929 0 : if(table) *table=__PLUMED_WRAPPER_CXX_NULLPTR;
3930 : }
3931 9 : }
3932 : __PLUMED_WRAPPER_INTERNALS_END
3933 :
3934 : #endif /*}*/
3935 :
3936 :
3937 : #if __PLUMED_WRAPPER_REEXPORT_SYMBOL_TABLE
3938 :
3939 : /*
3940 : Here is the case where plumed_symbol_table is
3941 : visible as extern. We first declare it (together with plumed_symbol_table_init) ...
3942 : */
3943 :
3944 : __PLUMED_WRAPPER_EXTERN_C_BEGIN
3945 : extern
3946 : plumed_symbol_table_type plumed_symbol_table;
3947 : __PLUMED_WRAPPER_EXTERN_C_END
3948 : __PLUMED_WRAPPER_EXTERN_C_BEGIN
3949 : extern
3950 : void plumed_symbol_table_init(void);
3951 : __PLUMED_WRAPPER_EXTERN_C_END
3952 :
3953 : /*
3954 : ... and then make available a function that returns the address
3955 : of the symbol table.
3956 : */
3957 : __PLUMED_WRAPPER_C_BEGIN
3958 683278 : plumed_symbol_table_type* plumed_symbol_table_reexport() {
3959 : /* make sure the table is initialized */
3960 683278 : plumed_symbol_table_init();
3961 709563 : return &plumed_symbol_table;
3962 : }
3963 : __PLUMED_WRAPPER_C_END
3964 :
3965 : #else
3966 :
3967 : /*
3968 : Here is the case where plumed_symbol_table is not
3969 : visible as extern. We thus assume that plumed_symbol_table_reexport is
3970 : available.
3971 : */
3972 :
3973 : __PLUMED_WRAPPER_EXTERN_C_BEGIN
3974 : extern plumed_symbol_table_type* plumed_symbol_table_reexport();
3975 : __PLUMED_WRAPPER_EXTERN_C_END
3976 : #endif
3977 :
3978 :
3979 : /*
3980 : Returns the global pointers, either those available at link time or those
3981 : found in the library loaded at PLUMED_KERNEL env var.
3982 : If plumed_symbol_table_ptr is not NULL, it is used to return a pointer to the symbol table
3983 : (if available).
3984 : Notice that problems can be detected checking if the functions have a NULL ptr.
3985 : On the other hand, the symbol table pointer might be NULL just because the plumed version is <=2.4.
3986 : If handle is not NULL, it is used to return a dlopen handle that could be subsequently dlclosed.
3987 : */
3988 : __PLUMED_WRAPPER_INTERNALS_BEGIN
3989 699260 : void plumed_retrieve_functions(plumed_plumedmain_function_holder* functions, plumed_symbol_table_type** plumed_symbol_table_ptr,void** handle) {
3990 : #if ! __PLUMED_WRAPPER_LINK_RUNTIME
3991 : /*
3992 : Real interface, constructed using the symbol table obtained with plumed_symbol_table_reexport.
3993 : This makes the symbols hardcoded and independent of a mis-set PLUMED_KERNEL variable.
3994 : */
3995 699260 : plumed_symbol_table_type* ptr=plumed_symbol_table_reexport();
3996 713338 : if(plumed_symbol_table_ptr) *plumed_symbol_table_ptr=ptr;
3997 713338 : if(handle) *handle=__PLUMED_WRAPPER_CXX_NULLPTR;
3998 713338 : if(functions) *functions=ptr->functions;
3999 : #elif ! defined(__PLUMED_HAS_DLOPEN)
4000 : /*
4001 : When dlopen is not available, we hard code them to NULL
4002 : */
4003 : __PLUMED_FPRINTF(stderr,"+++ PLUMED has been compiled without dlopen and without a static kernel +++\n");
4004 : plumed_plumedmain_function_holder g= {__PLUMED_WRAPPER_CXX_NULLPTR,__PLUMED_WRAPPER_CXX_NULLPTR,__PLUMED_WRAPPER_CXX_NULLPTR};
4005 : if(plumed_symbol_table_ptr) *plumed_symbol_table_ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
4006 : if(handle) *handle=__PLUMED_WRAPPER_CXX_NULLPTR;
4007 : if(functions) *functions=g;
4008 : #else
4009 : /*
4010 : On the other hand, for runtime binding, we use dlsym to find the relevant functions.
4011 : */
4012 : plumed_plumedmain_function_holder g;
4013 : /* search is done once and only once */
4014 : const char* path;
4015 : void* p;
4016 : char* debug;
4017 : int dlopenmode;
4018 : /* possible value of PLUMED_LOAD_NAMESPACE environment variable */
4019 : char *load_namespace;
4020 : g.create=__PLUMED_WRAPPER_CXX_NULLPTR;
4021 : g.cmd=__PLUMED_WRAPPER_CXX_NULLPTR;
4022 : g.finalize=__PLUMED_WRAPPER_CXX_NULLPTR;
4023 : path=__PLUMED_GETENV("PLUMED_KERNEL");
4024 : p=__PLUMED_WRAPPER_CXX_NULLPTR;
4025 : debug=__PLUMED_GETENV("PLUMED_LOAD_DEBUG");
4026 : dlopenmode=0;
4027 : if(plumed_symbol_table_ptr) *plumed_symbol_table_ptr=__PLUMED_WRAPPER_CXX_NULLPTR;
4028 : if(handle) *handle=__PLUMED_WRAPPER_CXX_NULLPTR;
4029 : #ifdef __PLUMED_DEFAULT_KERNEL
4030 : /*
4031 : This variable allows a default path for the kernel to be hardcoded.
4032 : Can be useful for hardcoding the predefined plumed location
4033 : still allowing the user to override this choice setting PLUMED_KERNEL.
4034 : The path should be chosen at compile time adding e.g.
4035 : -D__PLUMED_DEFAULT_KERNEL=/opt/local/lib/libplumed.dylib
4036 : */
4037 : /* This is required to add quotes */
4038 : #define PLUMED_QUOTE_DIRECT(name) #name
4039 : #define PLUMED_QUOTE(macro) PLUMED_QUOTE_DIRECT(macro)
4040 : if(! (path && (*path) )) path=PLUMED_QUOTE(__PLUMED_DEFAULT_KERNEL);
4041 : #endif
4042 : #if defined(__PLUMED_PROGRAM_NAME) && defined(__PLUMED_SOEXT)
4043 : if(! (path && (*path) )) path="lib" __PLUMED_PROGRAM_NAME "Kernel." __PLUMED_SOEXT;
4044 : #endif
4045 : if(path && (*path)) {
4046 : __PLUMED_FPRINTF(stderr,"+++ Loading the PLUMED kernel runtime +++\n");
4047 : __PLUMED_FPRINTF(stderr,"+++ PLUMED_KERNEL=\"%s\" +++\n",path);
4048 : if(debug) __PLUMED_FPRINTF(stderr,"+++ Loading with mode RTLD_NOW");
4049 : dlopenmode=RTLD_NOW;
4050 : load_namespace = __PLUMED_GETENV("PLUMED_LOAD_NAMESPACE");
4051 : if(load_namespace && !__PLUMED_WRAPPER_STD strcmp(load_namespace,"GLOBAL")) {
4052 : dlopenmode=dlopenmode|RTLD_GLOBAL;
4053 : if(debug) __PLUMED_FPRINTF(stderr,"|RTLD_GLOBAL");
4054 : } else {
4055 : dlopenmode=dlopenmode|RTLD_LOCAL;
4056 : if(debug) __PLUMED_FPRINTF(stderr,"|RTLD_LOCAL");
4057 : }
4058 : #ifdef RTLD_DEEPBIND
4059 : #if __PLUMED_WRAPPER_ENABLE_RTLD_DEEPBIND
4060 : if(!__PLUMED_GETENV("PLUMED_LOAD_NODEEPBIND")) {
4061 : dlopenmode=dlopenmode|RTLD_DEEPBIND;
4062 : if(debug) __PLUMED_FPRINTF(stderr,"|RTLD_DEEPBIND");
4063 : }
4064 : #endif
4065 : #endif
4066 : if(debug) __PLUMED_FPRINTF(stderr," +++\n");
4067 : p=plumed_attempt_dlopen(path,dlopenmode);
4068 : if(p) plumed_search_symbols(p,&g,plumed_symbol_table_ptr);
4069 : }
4070 : if(handle) *handle=p;
4071 : if(functions) *functions=g;
4072 : #endif
4073 713338 : }
4074 : __PLUMED_WRAPPER_INTERNALS_END
4075 :
4076 : /**
4077 : Implementation.
4078 : Small object used to store pointers directly into the plumed object defined in Plumed.h.
4079 : This allows avoiding the extra function call to plumed_retrieve_functions at every cmd,
4080 : at the cost of an extra indirection.
4081 : */
4082 : typedef struct {
4083 : /* allows errors with pointers to be found when debugging */
4084 : char magic[6];
4085 : /* reference count. this is only used with PLUMED<=2.8. Later versions have an internal thread-safe reference counter. */
4086 : int refcount;
4087 : /* handler to dlopened library. NULL if there was no library opened */
4088 : void* dlhandle;
4089 : /* non zero if, upon destruction, the library should be dlclosed */
4090 : int dlclose;
4091 : /* 1 if path to kernel was taken from PLUMED_KERNEL var, 0 otherwise */
4092 : int used_plumed_kernel;
4093 : /* function pointers */
4094 : plumed_plumedmain_function_holder functions;
4095 : /* pointer to the symbol table. NULL if kernel <=2.4 */
4096 : plumed_symbol_table_type* table;
4097 : /* pointer to plumed object */
4098 : void* p;
4099 : } plumed_implementation;
4100 :
4101 : __PLUMED_WRAPPER_INTERNALS_BEGIN
4102 725063 : plumed_implementation* plumed_malloc_pimpl() {
4103 : plumed_implementation* pimpl;
4104 : /* allocate space for implementation object. this is free-ed in plumed_finalize(). */
4105 725062 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, plumed_malloc(sizeof(plumed_implementation)));
4106 718498 : if(!pimpl) {
4107 0 : __PLUMED_FPRINTF(stderr,"+++ Allocation error +++\n");
4108 0 : __PLUMED_WRAPPER_STD abort();
4109 : }
4110 : /* cppcheck-suppress nullPointerRedundantCheck */
4111 718498 : __PLUMED_WRAPPER_STD memcpy(pimpl->magic,"pLuMEd",6);
4112 : /* cppcheck-suppress nullPointerRedundantCheck */
4113 718498 : pimpl->refcount=1;
4114 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4115 : /* cppcheck-suppress nullPointerRedundantCheck */
4116 : __PLUMED_FPRINTF(stderr,"refcount: new at %p\n",__PLUMED_WRAPPER_STATIC_CAST(void*,pimpl));
4117 : #endif
4118 : /* cppcheck-suppress nullPointerRedundantCheck */
4119 718498 : pimpl->dlhandle=__PLUMED_WRAPPER_CXX_NULLPTR;
4120 : /* cppcheck-suppress nullPointerRedundantCheck */
4121 718498 : pimpl->dlclose=0;
4122 : /* cppcheck-suppress nullPointerRedundantCheck */
4123 718498 : pimpl->used_plumed_kernel=0;
4124 : /* cppcheck-suppress nullPointerRedundantCheck */
4125 718498 : pimpl->functions.create=__PLUMED_WRAPPER_CXX_NULLPTR;
4126 : /* cppcheck-suppress nullPointerRedundantCheck */
4127 718498 : pimpl->functions.cmd=__PLUMED_WRAPPER_CXX_NULLPTR;
4128 : /* cppcheck-suppress nullPointerRedundantCheck */
4129 718498 : pimpl->functions.finalize=__PLUMED_WRAPPER_CXX_NULLPTR;
4130 : /* cppcheck-suppress nullPointerRedundantCheck */
4131 718498 : pimpl->table=__PLUMED_WRAPPER_CXX_NULLPTR;
4132 : /* cppcheck-suppress nullPointerRedundantCheck */
4133 718498 : pimpl->p=__PLUMED_WRAPPER_CXX_NULLPTR;
4134 718498 : return pimpl;
4135 : }
4136 : __PLUMED_WRAPPER_INTERNALS_END
4137 :
4138 : #ifndef NDEBUG
4139 :
4140 : __PLUMED_WRAPPER_INTERNALS_BEGIN
4141 : int plumed_check_pimpl(plumed_implementation*pimpl) {
4142 : if(!pimpl) return 0;
4143 : if(__PLUMED_WRAPPER_STD memcmp(pimpl->magic,"pLuMEd",6)) return 0;
4144 : return 1;
4145 : }
4146 : __PLUMED_WRAPPER_INTERNALS_END
4147 : #endif
4148 :
4149 : /* C wrappers: */
4150 :
4151 : __PLUMED_WRAPPER_C_BEGIN
4152 724813 : plumed plumed_create(void) {
4153 : /* returned object */
4154 : plumed p;
4155 : /* pointer to implementation */
4156 : plumed_implementation* pimpl;
4157 : /* possible value of PLUMED_LOAD_DLCLOSE environment variable */
4158 : char *load_dlclose;
4159 : /* allocate space for implementation object. this is free-ed in plumed_finalize(). */
4160 724813 : pimpl=plumed_malloc_pimpl();
4161 : /* store pointers in pimpl */
4162 718244 : plumed_retrieve_functions(&pimpl->functions,&pimpl->table,&pimpl->dlhandle);
4163 : #if __PLUMED_WRAPPER_LINK_RUNTIME
4164 : /* note if PLUMED_KERNEL variable was used */
4165 : pimpl->used_plumed_kernel=1;
4166 : #endif
4167 : /* note if handle should not be dlclosed */
4168 739084 : pimpl->dlclose=1;
4169 739084 : load_dlclose = __PLUMED_GETENV("PLUMED_LOAD_DLCLOSE");
4170 795789 : if(load_dlclose && !__PLUMED_WRAPPER_STD strcmp(load_dlclose,"no")) pimpl->dlclose=0;
4171 : /* in case of failure, return */
4172 : /* the resulting object should be plumed_finalized, though you cannot use plumed_cmd */
4173 795789 : if(!pimpl->functions.create) {
4174 : /* store pimpl in returned object */
4175 : p.p=pimpl;
4176 0 : return p;
4177 : }
4178 : assert(pimpl->functions.cmd);
4179 : assert(pimpl->functions.finalize);
4180 : /* obtain object */
4181 795789 : pimpl->p=(*(pimpl->functions.create))();
4182 : /* notice: we do not assert pimpl->p since in principle it might be nullptr */
4183 : /* user might identify this using plumed_valid() */
4184 : /* store pimpl in returned object */
4185 : p.p=pimpl;
4186 789340 : return p;
4187 : }
4188 : __PLUMED_WRAPPER_C_END
4189 :
4190 : __PLUMED_WRAPPER_C_BEGIN
4191 9 : plumed plumed_create_dlopen(const char*path) {
4192 : int dlopenmode;
4193 : /* plumed_create_dlopen always uses RTLD_LOCAL and, when possible, RTLD_DEEPBIND to allow multiple versions */
4194 : #ifdef __PLUMED_HAS_DLOPEN
4195 : dlopenmode=RTLD_NOW|RTLD_LOCAL;
4196 : #ifdef RTLD_DEEPBIND
4197 : #if __PLUMED_WRAPPER_ENABLE_RTLD_DEEPBIND
4198 9 : if(!__PLUMED_GETENV("PLUMED_LOAD_NODEEPBIND")) dlopenmode=dlopenmode|RTLD_DEEPBIND;
4199 : #endif
4200 : #endif
4201 : #else
4202 : dlopenmode=0;
4203 : #endif
4204 9 : return plumed_create_dlopen2(path,dlopenmode);
4205 : }
4206 : __PLUMED_WRAPPER_C_END
4207 :
4208 : __PLUMED_WRAPPER_C_BEGIN
4209 9 : plumed plumed_create_dlsym(void* dlhandle) {
4210 : /* returned object */
4211 : plumed p;
4212 : /* pointer to implementation */
4213 : plumed_implementation* pimpl;
4214 : /* allocate space for implementation object. this is free-ed in plumed_finalize(). */
4215 9 : pimpl=plumed_malloc_pimpl();
4216 : #ifdef __PLUMED_HAS_DLOPEN
4217 9 : pimpl->dlhandle=dlhandle;
4218 9 : plumed_search_symbols(pimpl->dlhandle,&pimpl->functions,&pimpl->table);
4219 : #endif
4220 9 : if(!pimpl->functions.create) {
4221 : p.p=pimpl;
4222 0 : return p;
4223 : }
4224 : assert(pimpl->functions.cmd);
4225 : assert(pimpl->functions.finalize);
4226 : /* obtain object */
4227 9 : pimpl->p=(*(pimpl->functions.create))();
4228 : /* notice: we do not assert pimpl->p since in principle it might be nullptr */
4229 : /* user might identify this using plumed_valid() */
4230 : /* store pimpl in returned object */
4231 : p.p=pimpl;
4232 9 : return p;
4233 : }
4234 : __PLUMED_WRAPPER_C_END
4235 :
4236 : __PLUMED_WRAPPER_C_BEGIN
4237 9 : plumed plumed_create_dlopen2(const char*path,int mode) {
4238 : #ifdef __PLUMED_HAS_DLOPEN
4239 : /* returned object */
4240 : plumed p;
4241 : /* pointer to implementation */
4242 : plumed_implementation* pimpl;
4243 : /* handler */
4244 : void* dlhandle;
4245 : dlhandle=__PLUMED_WRAPPER_CXX_NULLPTR;
4246 9 : if(path) dlhandle=plumed_attempt_dlopen(path,mode);
4247 : /* a NULL handle implies the file could not be loaded */
4248 9 : if(dlhandle) {
4249 9 : p=plumed_create_dlsym(dlhandle);
4250 : /* obtain pimpl */
4251 9 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4252 : /* make sure the handler is closed when plumed is finalized */
4253 9 : pimpl->dlclose=1;
4254 9 : return p;
4255 : }
4256 : #else
4257 : (void) path;
4258 : (void) mode;
4259 : #endif
4260 0 : return plumed_create_invalid();
4261 : }
4262 : __PLUMED_WRAPPER_C_END
4263 :
4264 : __PLUMED_WRAPPER_C_BEGIN
4265 7598993 : plumed plumed_create_reference(plumed p) {
4266 : plumed_implementation* pimpl;
4267 : /* obtain pimpl */
4268 7598993 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4269 : assert(plumed_check_pimpl(pimpl));
4270 : /* increase reference count */
4271 : /* with PLUMED > 2.8, we can use an internal reference counter which is thread safe */
4272 7598993 : if(pimpl->p && pimpl->table && pimpl->table->version>3) {
4273 7575597 : pimpl->table->create_reference(pimpl->p);
4274 : } else {
4275 23396 : pimpl->refcount++;
4276 : }
4277 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4278 : __PLUMED_FPRINTF(stderr,"refcount: increase at %p\n",__PLUMED_WRAPPER_STATIC_CAST(void*,pimpl));
4279 : #endif
4280 7577264 : return p;
4281 : }
4282 : __PLUMED_WRAPPER_C_END
4283 :
4284 : __PLUMED_WRAPPER_C_BEGIN
4285 2 : plumed plumed_create_reference_v(void*v) {
4286 2 : return plumed_create_reference(plumed_v2c(v));
4287 : }
4288 : __PLUMED_WRAPPER_C_END
4289 :
4290 : __PLUMED_WRAPPER_C_BEGIN
4291 8 : plumed plumed_create_reference_f(const char*f) {
4292 8 : return plumed_create_reference(plumed_f2c(f));
4293 : }
4294 : __PLUMED_WRAPPER_C_END
4295 :
4296 : __PLUMED_WRAPPER_C_BEGIN
4297 2 : plumed plumed_create_invalid() {
4298 : plumed p;
4299 : plumed_implementation* pimpl;
4300 2 : pimpl=plumed_malloc_pimpl();
4301 : p.p=pimpl;
4302 2 : return p;
4303 : }
4304 : __PLUMED_WRAPPER_C_END
4305 :
4306 : __PLUMED_WRAPPER_C_BEGIN
4307 357 : void plumed_cmd(plumed p,const char*key,const void*val) {
4308 : plumed_implementation* pimpl;
4309 : /* obtain pimpl */
4310 357 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4311 : assert(plumed_check_pimpl(pimpl));
4312 357 : if(!pimpl->p) {
4313 0 : __PLUMED_FPRINTF(stderr,"+++ ERROR: You are trying to use an invalid plumed object. +++\n");
4314 0 : if(pimpl->used_plumed_kernel) __PLUMED_FPRINTF(stderr,"+++ Check your PLUMED_KERNEL environment variable. +++\n");
4315 0 : __PLUMED_WRAPPER_STD abort();
4316 : }
4317 : assert(pimpl->functions.create);
4318 : assert(pimpl->functions.cmd);
4319 : assert(pimpl->functions.finalize);
4320 : /* execute */
4321 357 : (*(pimpl->functions.cmd))(pimpl->p,key,val);
4322 357 : }
4323 : __PLUMED_WRAPPER_C_END
4324 :
4325 : __PLUMED_WRAPPER_C_BEGIN
4326 19425 : void plumed_cmd_safe_nothrow(plumed p,const char*key,plumed_safeptr safe,plumed_nothrow_handler nothrow) {
4327 : plumed_implementation* pimpl;
4328 : /* This is to allow caller to use a null handler to imply that handling is not done */
4329 19425 : if(!nothrow.handler) {
4330 37 : plumed_cmd_safe(p,key,safe);
4331 37 : return;
4332 : }
4333 : /* obtain pimpl */
4334 19388 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4335 : assert(plumed_check_pimpl(pimpl));
4336 19388 : if(!pimpl->p) {
4337 0 : if(pimpl->used_plumed_kernel) {
4338 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);
4339 : } else {
4340 0 : nothrow.handler(nothrow.ptr,1,"You are trying to use plumed, but it is not available.",__PLUMED_WRAPPER_CXX_NULLPTR);
4341 : }
4342 0 : return;
4343 : }
4344 : assert(pimpl->functions.create);
4345 : assert(pimpl->functions.cmd);
4346 : assert(pimpl->functions.finalize);
4347 : /* execute */
4348 19388 : if(pimpl->table && pimpl->table->version>2) (*(pimpl->table->cmd_safe_nothrow))(pimpl->p,key,safe,nothrow);
4349 0 : else if(pimpl->table && pimpl->table->version>1) (*(pimpl->table->cmd_nothrow))(pimpl->p,key,safe.ptr,nothrow);
4350 0 : else (*(pimpl->functions.cmd))(pimpl->p,key,safe.ptr);
4351 : }
4352 : __PLUMED_WRAPPER_C_END
4353 :
4354 : __PLUMED_WRAPPER_C_BEGIN
4355 0 : void plumed_cmd_nothrow(plumed p,const char*key,const void*val,plumed_nothrow_handler nothrow) {
4356 : plumed_safeptr safe;
4357 0 : safe.ptr=val;
4358 0 : safe.flags=0;
4359 0 : safe.nelem=0;
4360 0 : safe.shape=__PLUMED_WRAPPER_CXX_NULLPTR;
4361 0 : safe.opt=__PLUMED_WRAPPER_CXX_NULLPTR;
4362 0 : plumed_cmd_safe_nothrow(p,key,safe,nothrow);
4363 0 : }
4364 : __PLUMED_WRAPPER_C_END
4365 :
4366 : __PLUMED_WRAPPER_C_BEGIN
4367 95 : void plumed_cmd_safe(plumed p,const char*key,plumed_safeptr safe) {
4368 : plumed_implementation* pimpl;
4369 : /* obtain pimpl */
4370 95 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4371 : assert(plumed_check_pimpl(pimpl));
4372 95 : if(!pimpl->p) {
4373 0 : __PLUMED_FPRINTF(stderr,"+++ ERROR: You are trying to use an invalid plumed object. +++\n");
4374 0 : if(pimpl->used_plumed_kernel) __PLUMED_FPRINTF(stderr,"+++ Check your PLUMED_KERNEL environment variable. +++\n");
4375 0 : __PLUMED_WRAPPER_STD abort();
4376 : }
4377 : assert(pimpl->functions.create);
4378 : assert(pimpl->functions.cmd);
4379 : assert(pimpl->functions.finalize);
4380 : /* execute */
4381 95 : if(pimpl->table && pimpl->table->version>2) (*(pimpl->table->cmd_safe))(pimpl->p,key,safe);
4382 0 : else (*(pimpl->functions.cmd))(pimpl->p,key,safe.ptr);
4383 95 : }
4384 : __PLUMED_WRAPPER_C_END
4385 :
4386 :
4387 : __PLUMED_WRAPPER_C_BEGIN
4388 8532502 : void plumed_finalize(plumed p) {
4389 : plumed_implementation* pimpl;
4390 : /* obtain pimpl */
4391 8532502 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4392 : assert(plumed_check_pimpl(pimpl));
4393 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4394 : __PLUMED_FPRINTF(stderr,"refcount: decrease at %p\n",__PLUMED_WRAPPER_STATIC_CAST(void*,pimpl));
4395 : #endif
4396 : /* with PLUMED > 2.8, we can use an internal reference counter which is thread safe */
4397 8532502 : if(pimpl->p && pimpl->table && pimpl->table->version>3) {
4398 8467158 : if(pimpl->table->delete_reference(pimpl->p)>0) return;
4399 : } else {
4400 65344 : if(--pimpl->refcount>0) return;
4401 : }
4402 : /* to allow finalizing an invalid plumed object, we only call
4403 : finalize if the object is valid */
4404 778385 : if(pimpl->p) {
4405 : assert(pimpl->functions.create);
4406 : assert(pimpl->functions.cmd);
4407 : assert(pimpl->functions.finalize);
4408 : /* finalize */
4409 778383 : (*(pimpl->functions.finalize))(pimpl->p);
4410 : }
4411 : #ifdef __PLUMED_HAS_DLOPEN
4412 : /* dlclose library */
4413 758440 : if(pimpl->dlhandle && pimpl->dlclose) {
4414 9 : if(__PLUMED_GETENV("PLUMED_LOAD_DEBUG")) __PLUMED_FPRINTF(stderr,"+++ Unloading library\n");
4415 9 : dlclose(pimpl->dlhandle);
4416 : }
4417 : #endif
4418 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4419 : __PLUMED_FPRINTF(stderr,"refcount: delete at %p\n",__PLUMED_WRAPPER_STATIC_CAST(void*,pimpl));
4420 : #endif
4421 : /* free pimpl space */
4422 758439 : plumed_free(pimpl);
4423 : }
4424 : __PLUMED_WRAPPER_C_END
4425 :
4426 : __PLUMED_WRAPPER_C_BEGIN
4427 23 : int plumed_valid(plumed p) {
4428 : plumed_implementation* pimpl;
4429 : /* obtain pimpl */
4430 23 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4431 : assert(plumed_check_pimpl(pimpl));
4432 24 : if(pimpl->p) return 1;
4433 2 : else return 0;
4434 : }
4435 : __PLUMED_WRAPPER_C_END
4436 :
4437 : __PLUMED_WRAPPER_C_BEGIN
4438 42 : int plumed_use_count(plumed p) {
4439 : plumed_implementation* pimpl;
4440 : /* obtain pimpl */
4441 42 : pimpl=__PLUMED_WRAPPER_STATIC_CAST(plumed_implementation*, p.p);
4442 : assert(plumed_check_pimpl(pimpl));
4443 : /* with PLUMED > 2.8, we can use an internal reference counter which is thread safe */
4444 42 : if(pimpl->p && pimpl->table && pimpl->table->version>3) {
4445 42 : return pimpl->table->use_count(pimpl->p);
4446 : } else {
4447 0 : return pimpl->refcount;
4448 : }
4449 : }
4450 : __PLUMED_WRAPPER_C_END
4451 :
4452 : __PLUMED_WRAPPER_C_BEGIN
4453 9 : int plumed_installed(void) {
4454 : plumed p;
4455 : int result;
4456 9 : p=plumed_create();
4457 9 : result=plumed_valid(p);
4458 9 : plumed_finalize(p);
4459 9 : return result;
4460 : }
4461 : __PLUMED_WRAPPER_C_END
4462 :
4463 : __PLUMED_WRAPPER_C_BEGIN
4464 723909 : void* plumed_malloc(__PLUMED_WRAPPER_STD size_t size) {
4465 : void* ptr;
4466 723910 : ptr=__PLUMED_WRAPPER_STD malloc(size);
4467 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4468 : if(ptr) fprintf(stderr,"plumed_malloc: %p\n",ptr);
4469 : #endif
4470 723909 : return ptr;
4471 : }
4472 : __PLUMED_WRAPPER_C_END
4473 :
4474 : __PLUMED_WRAPPER_C_BEGIN
4475 744190 : void plumed_free(void* ptr) {
4476 744191 : __PLUMED_WRAPPER_STD free(ptr);
4477 : #if __PLUMED_WRAPPER_DEBUG_REFCOUNT
4478 : fprintf(stderr,"plumed_free: %p\n",ptr);
4479 : #endif
4480 744191 : }
4481 : __PLUMED_WRAPPER_C_END
4482 :
4483 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
4484 :
4485 : __PLUMED_WRAPPER_EXTERN_C_BEGIN
4486 :
4487 : /* we declare a Plumed_g_main object here, in such a way that it is always available */
4488 :
4489 : static plumed plumed_gmain= {__PLUMED_WRAPPER_CXX_NULLPTR};
4490 :
4491 589 : plumed plumed_global(void) {
4492 589 : return plumed_gmain;
4493 : }
4494 :
4495 61 : void plumed_gcreate(void) {
4496 : /* should be created once */
4497 : assert(plumed_gmain.p==__PLUMED_WRAPPER_CXX_NULLPTR);
4498 61 : plumed_gmain=plumed_create();
4499 61 : }
4500 :
4501 78 : void plumed_gcmd(const char*key,const void*val) {
4502 78 : plumed_cmd(plumed_gmain,key,val);
4503 78 : }
4504 :
4505 : /* cppcheck-suppress passedByValue */
4506 0 : void plumed_gcmd_safe(const char*key,plumed_safeptr safe) {
4507 0 : plumed_cmd_safe(plumed_gmain,key,safe);
4508 0 : }
4509 :
4510 61 : void plumed_gfinalize(void) {
4511 61 : plumed_finalize(plumed_gmain);
4512 61 : plumed_gmain.p=__PLUMED_WRAPPER_CXX_NULLPTR;
4513 61 : }
4514 :
4515 24 : int plumed_ginitialized(void) {
4516 24 : if(plumed_gmain.p) return 1;
4517 16 : else return 0;
4518 : }
4519 :
4520 8 : int plumed_gvalid() {
4521 : assert(plumed_gmain.p);
4522 8 : return plumed_valid(plumed_gmain);
4523 : }
4524 :
4525 : __PLUMED_WRAPPER_EXTERN_C_END
4526 :
4527 : #endif /*}*/
4528 :
4529 : __PLUMED_WRAPPER_C_BEGIN
4530 56 : void plumed_c2f(plumed p,char*c) {
4531 : unsigned i;
4532 : unsigned char* cc;
4533 : /*
4534 : Convert the address stored in p.p into a proper FORTRAN string
4535 : made of only ASCII characters. For this to work, the two following
4536 : assertions should be satisfied:
4537 : */
4538 : assert(CHAR_BIT<=12);
4539 : assert(sizeof(p.p)<=16);
4540 :
4541 : assert(c);
4542 : cc=__PLUMED_WRAPPER_REINTERPRET_CAST(unsigned char*,&p.p);
4543 504 : for(i=0; i<sizeof(p.p); i++) {
4544 : /*
4545 : characters will range between '0' (ASCII 48) and 'o' (ASCII 111=48+63)
4546 : */
4547 448 : c[2*i]=cc[i]/64+48;
4548 448 : c[2*i+1]=cc[i]%64+48;
4549 : }
4550 504 : for(; i<16; i++) {
4551 448 : c[2*i]=' ';
4552 448 : c[2*i+1]=' ';
4553 : }
4554 56 : }
4555 : __PLUMED_WRAPPER_C_END
4556 :
4557 : __PLUMED_WRAPPER_C_BEGIN
4558 373 : plumed plumed_f2c(const char*c) {
4559 : plumed p;
4560 : unsigned i;
4561 : unsigned char* cc;
4562 :
4563 : assert(CHAR_BIT<=12);
4564 : assert(sizeof(p.p)<=16);
4565 :
4566 : assert(c);
4567 :
4568 : /*
4569 : needed to avoid cppcheck warning on uninitialized p
4570 : */
4571 373 : p.p=__PLUMED_WRAPPER_CXX_NULLPTR;
4572 : cc=__PLUMED_WRAPPER_REINTERPRET_CAST(unsigned char*,&p.p);
4573 3357 : for(i=0; i<sizeof(p.p); i++) {
4574 : assert(c[2*i]>=48 && c[2*i]<48+64);
4575 : assert(c[2*i+1]>=48 && c[2*i+1]<48+64);
4576 : /*
4577 : perform the reversed transform
4578 : */
4579 2984 : cc[i]=(c[2*i]-48)*64 + (c[2*i+1]-48);
4580 : }
4581 3357 : for(; i<16; i++) {
4582 : assert(c[2*i]==' ');
4583 : assert(c[2*i+1]==' ');
4584 : }
4585 373 : return p;
4586 : }
4587 : __PLUMED_WRAPPER_C_END
4588 :
4589 : __PLUMED_WRAPPER_C_BEGIN
4590 2 : void* plumed_c2v(plumed p) {
4591 : assert(plumed_check_pimpl(__PLUMED_WRAPPER_REINTERPRET_CAST(plumed_implementation*,p.p)));
4592 2 : return p.p;
4593 : }
4594 : __PLUMED_WRAPPER_C_END
4595 :
4596 : __PLUMED_WRAPPER_C_BEGIN
4597 2 : plumed plumed_v2c(void* v) {
4598 : assert(plumed_check_pimpl(__PLUMED_WRAPPER_REINTERPRET_CAST(plumed_implementation*,v)));
4599 : plumed p;
4600 : p.p=v;
4601 2 : return p;
4602 : }
4603 : __PLUMED_WRAPPER_C_END
4604 :
4605 : #if __PLUMED_WRAPPER_FORTRAN /*{*/
4606 :
4607 : /*
4608 : Fortran wrappers
4609 : These are just like the global C wrappers. They are
4610 : just defined here and not declared since they
4611 : should not be used from c/c++ anyway.
4612 :
4613 : We use a macro that does the following:
4614 : - declare a static function named NAME_static
4615 : - declare a number of functions named NAME_ etc, with all possible
4616 : fortran mangling schemes (zero, one, or two underscores, lower and upper case)
4617 : - define the NAME_static function.
4618 :
4619 : The static function is used basically as an inline function in a C-compatible manner.
4620 : */
4621 :
4622 : #define __PLUMED_IMPLEMENT_FORTRAN(lower,upper,arg1,arg2) \
4623 : static void lower ## _static arg1; \
4624 : extern void lower arg1 {lower ## _static arg2;} \
4625 : extern void lower ##_ arg1 {lower ## _static arg2;} \
4626 : extern void lower ##__ arg1 {lower ## _static arg2;} \
4627 : extern void upper arg1 {lower ## _static arg2;} \
4628 : extern void upper ##_ arg1 {lower ## _static arg2;} \
4629 : extern void upper ##__ arg1 {lower ## _static arg2;} \
4630 : static void lower ## _static arg1
4631 :
4632 : /* FORTRAN wrappers would only make sense as extern "C" */
4633 :
4634 : __PLUMED_WRAPPER_EXTERN_C_BEGIN
4635 :
4636 36 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create,PLUMED_F_CREATE,(char*c),(c)) {
4637 18 : plumed_c2f(plumed_create(),c);
4638 18 : }
4639 :
4640 12 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create_dlopen,PLUMED_F_CREATE_DLOPEN,(char*path,char*c),(path,c)) {
4641 6 : plumed_c2f(plumed_create_dlopen(path),c);
4642 6 : }
4643 :
4644 12 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create_reference,PLUMED_F_CREATE_REFERENCE,(char* r,char*c),(r,c)) {
4645 6 : plumed_c2f(plumed_create_reference_f(r),c);
4646 6 : }
4647 :
4648 0 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_create_invalid,PLUMED_F_CREATE_INVALID,(char* c),(c)) {
4649 0 : plumed_c2f(plumed_create_invalid(),c);
4650 0 : }
4651 :
4652 558 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_cmd,PLUMED_F_CMD,(char*c,char*key,void*val),(c,key,val)) {
4653 279 : plumed_cmd(plumed_f2c(c),key,val);
4654 279 : }
4655 :
4656 60 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_finalize,PLUMED_F_FINALIZE,(char*c),(c)) {
4657 30 : plumed_finalize(plumed_f2c(c));
4658 30 : }
4659 :
4660 12 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_installed,PLUMED_F_INSTALLED,(int*i),(i)) {
4661 : assert(i);
4662 6 : *i=plumed_installed();
4663 6 : }
4664 :
4665 : /* New in PLUMED 2.5 */
4666 0 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_valid,PLUMED_F_VALID,(char*c,int*i),(c,i)) {
4667 : assert(i);
4668 0 : *i=plumed_valid(plumed_f2c(c));
4669 0 : }
4670 :
4671 36 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_use_count,PLUMED_F_USE_COUNT,(char*c,int*i),(c,i)) {
4672 : assert(i);
4673 18 : *i=plumed_use_count(plumed_f2c(c));
4674 18 : }
4675 :
4676 : /* New in PLUMED 2.8 */
4677 :
4678 : /* note: flags & (~0x1ffffff) removes bits that are set here (code and size) */
4679 :
4680 : #define __PLUMED_IMPLEMENT_F_SAFEPTR_INNER(type,type_,size,code,suffix) \
4681 : 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) {\
4682 : plumed_safeptr safe; \
4683 : safe.ptr=val; \
4684 : safe.nelem=nelem; \
4685 : safe.shape=shape; \
4686 : safe.flags= (flags & (~0x1ffffffu)) + 0x10000*code + size; \
4687 : safe.opt=opt; \
4688 : return safe; \
4689 : }
4690 :
4691 : #define __PLUMED_IMPLEMENT_F_SAFEPTR(type,type_,size,code) \
4692 : __PLUMED_IMPLEMENT_F_SAFEPTR_INNER(type,type_,size,code,) \
4693 : __PLUMED_IMPLEMENT_F_SAFEPTR_INNER(type,type_,size,code,_scalar)
4694 :
4695 : #define __PLUMED_IMPLEMENT_F_SAFEPTR_EMPTY(type,type_,code) \
4696 : __PLUMED_IMPLEMENT_F_SAFEPTR(type,type_,0,code)
4697 :
4698 : #define __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(type,type_,code) \
4699 : __PLUMED_IMPLEMENT_F_SAFEPTR(type,type_,sizeof(type),code)
4700 :
4701 24 : __PLUMED_IMPLEMENT_F_SAFEPTR_EMPTY(void,ptr,0)
4702 1 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(float,float,4)
4703 19 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(double,double,4)
4704 0 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(long double,long_double,4)
4705 19 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(int,int,3)
4706 0 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(short,short,3)
4707 0 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(long,long,3)
4708 20 : __PLUMED_IMPLEMENT_F_SAFEPTR_SIZED(char,char,3)
4709 :
4710 : #if __PLUMED_WRAPPER_GLOBAL /*{*/
4711 :
4712 48 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_global,PLUMED_F_GLOBAL,(char*c),(c)) {
4713 24 : plumed_c2f(plumed_gmain,c);
4714 24 : }
4715 :
4716 36 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_ginitialized,PLUMED_F_GINITIALIZED,(int*i),(i)) {
4717 : assert(i);
4718 18 : *i=plumed_ginitialized();
4719 18 : }
4720 :
4721 28 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_gcreate,PLUMED_F_GCREATE,(void),()) {
4722 14 : plumed_gcreate();
4723 14 : }
4724 :
4725 156 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_gcmd,PLUMED_F_GCMD,(char*key,void*val),(key,val)) {
4726 78 : plumed_gcmd(key,val);
4727 78 : }
4728 :
4729 28 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_gfinalize,PLUMED_F_GFINALIZE,(void),()) {
4730 14 : plumed_gfinalize();
4731 14 : }
4732 :
4733 : /* New in PLUMED 2.5 */
4734 12 : __PLUMED_IMPLEMENT_FORTRAN(plumed_f_gvalid,PLUMED_F_GVALID,(int*i),(i)) {
4735 : assert(i);
4736 6 : *i=plumed_gvalid();
4737 6 : }
4738 :
4739 : #endif /*}*/
4740 :
4741 : __PLUMED_WRAPPER_EXTERN_C_END
4742 :
4743 : #endif /*}*/
4744 :
4745 : #endif /*}*/
4746 :
4747 : #endif /*}*/
4748 :
4749 : /* END OF DEFINITIONS */
4750 :
4751 : /* reset variable to allow it to be redefined upon re-inclusion */
4752 :
4753 : #undef __PLUMED_WRAPPER_IMPLEMENTATION_
4754 :
4755 : /* this macro is set in declarations */
4756 : #ifdef __PLUMED_WRAPPER_REDEFINE_CMD
4757 : #if defined(plumed_cmd)
4758 : #undef plumed_cmd
4759 : #endif
4760 : #define plumed_cmd __PLUMED_WRAPPER_REDEFINE_CMD
4761 : #endif
4762 :
4763 : /* this macro is set in declarations */
4764 : #ifdef __PLUMED_WRAPPER_REDEFINE_GCMD
4765 : #if defined(plumed_gcmd)
4766 : #undef plumed_gcmd
4767 : #endif
4768 : #define plumed_gcmd __PLUMED_WRAPPER_REDEFINE_GCMD
4769 : #endif
4770 :
4771 : /* this macro is set in declarations */
4772 : #ifdef __PLUMED_WRAPPER_REDEFINE_ERROR_RETHROW
4773 : #if defined(plumed_error_rethrow)
4774 : #undef plumed_error_rethrow
4775 : #endif
4776 : #define plumed_error_rethrow __PLUMED_WRAPPER_REDEFINE_ERROR_RETHROW
4777 : #endif
|