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