c++-gtk-utils
Classes | Functions
Cgu::Extension Namespace Reference

This namespace provides functions to execute scheme code on the guile VM. More...

Classes

class  GuileException
 
class  ReturnValueError
 
class  WrapperError
 

Functions

SCM exception_to_string (SCM key, SCM args)
 
void rethrow_guile_exception (SCM scm)
 
std::vector< long > list_to_vector_long (SCM scm)
 
std::vector< double > list_to_vector_double (SCM scm)
 
std::vector< std::string > list_to_vector_string (SCM scm)
 
long integer_to_long (SCM scm)
 
double real_to_double (SCM scm)
 
std::string string_to_string (SCM scm)
 
void * any_to_void (SCM scm)
 
template<class Translator >
auto exec (const std::string &preamble, const std::string &file, Translator translator) -> typename std::result_of< Translator(SCM)>::type
 
template<class Translator >
auto exec_shared (const std::string &preamble, const std::string &file, Translator translator) -> typename std::result_of< Translator(SCM)>::type
 

Detailed Description

This namespace provides functions to execute scheme code on the guile VM.

#include <c++-gtk-utils/extension.h>

The Extension::exec() and Extension::exec_shared() functions provided by this library allow any C++ program to execute files written in the scheme language on the guile VM as part of the C++ runtime. There are a number of reasons why this might be useful:

  • to enable the dynamic behaviour of the program to be altered without recompilation
  • to provide a plugin system
  • because some things are easier or quicker to do when done in a dynamically typed language such as scheme
  • because scheme is a nice language to use and highly extensible

To call Extension::exec() or Extension::exec_shared(), guile-2.0 >= 2.0.2, guile-2.2 >= 2.1.3 or guile-3.0 >= 3.0.0 is required.

Usage

Extension::exec() and Extension::exec_shared() take three arguments. The first is a preamble string, which sets out any top level definitions which the script file needs to see. This is mainly intended for argument passing to the script file, but can comprise any scheme code. It can also be an empty string. The second is the name of the scheme script file to be executed, with path. This file can contain scheme code of arbitrary complexity and length, and can incorporate guile modules and other scheme files.

The third argument is a translator. This is a function or callable object which takes the value to which the scheme file evaluates (in C++ terms, its return value) as an opaque SCM guile type (it is actually a pointer to a struct in the guile VM), and converts it to a suitable C++ representation using functions provided by libguile. The return value of the translator function comprises the return value of Extension::exec() and Extension::exec_shared().

Translators

Preformed translators are provided by this library to translate from scheme's integers, real numbers and strings to C++ longs, doubles and strings respectively (namely Extension::integer_to_long(), Extension::real_to_double() and Extension::string_to_string()), and from any uniform lists of these to C++ vectors of the corresponding type (Extension::list_to_vector_long(), Extension::list_to_vector_double() and Extension::list_to_vector_string(). There is also a translator for void return types (Extension::any_to_void()), where the scheme script is executed for its side effects, perhaps I/O, where the return value is ignored and any communication necessary is done by guile exceptions.

Any guile exception thrown by the code in the scheme file is trapped by the preformed translators and will be rethrown as an Extension::GuileException C++ exception. The preformed translators should suffice for most purposes, but custom translators can be provided by the user - see further below.

Example

Assume the following code is in a file called 'myip.scm'.

;; myip.scm
;; the following code assumes a top level definition of 'web-ip' is
;; passed, giving the URL of an IP address reflector
(use-modules (ice-9 regex)(web uri)(web client))
(let ([uri (build-uri 'http
#:host web-ip
#:port 80
#:path "/")])
(call-with-values
(lambda () (http-get uri))
(lambda (request body)
(match:substring
(string-match "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"
body)))))

This code requires guile >= 2.0.3, and makes a http request to the reflector, reads the body of the reply and then does a regex search on it to obtain the address. Courtesy of the good folks at DynDNS we can obtain our address with this:

using namespace Cgu;
std::cout << "IP address is: "
<< Extension::exec_shared("(define web-ip \"checkip.dyndns.com\")",
"./myip.scm",
<< std::endl;

This is easier than doing the same in C++ using, say, libsoup and std::regex. However it is unsatisfying where we do not want the code to block waiting for the reply. There are a number of possible approaches to this, but one is to provide the result to a glib main loop asynchronously via a Thread::TaskManager object. There are two possibilities for this. First, the Thread::TaskManager::make_task_when_full() method could be used, to which a fail callback could be passed to execute if guile throws an exception (say because the url does not resolve). Alternatively, the scheme code in myip.scm could wrap itself in a guile catch expression, and hand back a list of two strings, the first string of which indicates an error condition with description (or an empty string if there is no error), and the second the result on success, in which case Thread::TaskManager::make_task_when() or Thread::TaskManager::make_task_compose() could be called. This does the second:

;; myip.scm
;; the following code assumes a top level definition of 'web-ip' is
;; passed, giving the URL of an IP address reflector
(use-modules (ice-9 regex)(web uri)(web client))
(let ([uri (build-uri 'http
#:host web-ip
#:port 80
#:path "/")])
(catch
#t
(lambda () ;; the 'try' block
(call-with-values
(lambda () (http-get uri))
(lambda (request body)
(list "" ;; empty string for first element of list - no error
(match:substring
(string-match "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"
body)))))) ;; ip address as a string
(lambda (key . details) ;; the 'catch' block
(list (string-append "Exception in myip.scm: "
(object->string (cons key details))) ;; exception details
"")))) ;; empty string for second element of list - error
using namespace Cgu;
typedef std::vector<std::string> ResType;
auto when = Callback::to_unique(
Callback::lambda<const ResType&>([] (const ResType& res) {
if (!res[0].empty()) {
// display GtkMessageDialog object indicating failure
}
else {
// publish result in res[1] in some GTK widget
}
}
);
tm.make_task_when (
std::move(when),
0, // supply result to default glib main loop
[] () {
return Extension::exec_shared("(define web-ip \"checkip.dyndns.com\")",
"./myip.scm",
}
);

Extension::exec() and Extension::exec_shared()

Extension::exec() isolates the top level definitions of a task, including definitions in the preamble of a task or imported by guile's 'use-modules' or 'load' procedures, from the top level definitions of other tasks started by calls to Extension::exec(), by calling guile's 'make-fresh-user-module' procedure. Extension::exec_shared() does not do so: with Extension::exec_shared(), all scheme tasks executed by calls to that function will share the same top level. In addition, Extension::exec() loads the file passed to the function using the guile 'load' procedure, so that the first time the file is executed it is compiled into bytecode, whereas Extension::exec_shared() calls the 'primitive-load' procedure instead, which runs the file through the guile interpreter without converting it to bytecode.

The reason for this different behaviour of Extension::exec_shared() is that, as currently implemented in guile both the 'make-fresh-user-module' and 'load' procedures leak small amounts of memory. If a particular program is likely to call Extension::exec() more than about 5,000 or 10,000 times, it would be better to use Extension::exec_shared() instead.

From guile-2.0.2, Extension::exec() and Extension::exec_shared() do not need to be called only in the main program thread - and in the above example using a Thread::TaskManager object Extension::exec_shared() was not. However, one of the consequences of the behaviour mentioned above is that if Extension::exec_shared() is to be used instead of Extension::exec(), either concurrent calls to the function from different threads should be avoided, or (i) the preambles in calls to Extension::exec_shared() should be empty and (ii) tasks should not make clashing top level definitions in some other way, including by importing clashing definitions using 'use-modules' or 'load'. The need for Extension::exec_shared() to be called only in one thread in the example above was the reason why the TaskManager object in that example was set to have a maximum thread count of 1. In effect the TaskManager object was a dedicated serial dispatcher for all scheme tasks.

The calling by Extension::exec_shared() of 'primitive-load' instead of 'load' may have some small effect on efficiency. It it best for the file passed to that function to hand off any complex code to modules prepared using guile's modules interface (which will be compiled into bytecode), and which are then loaded using 'use-modules' the first time Extension::exec_shared() is called, or by having the first call to Extension::exec_shared() (and only the first call) import any needed files into the top level using 'load'.

Note that some guile global state may be shared between tasks whether Extension::exec() or Extension::exec_shared() is used. For example, if the guile 'add-to-load-path' procedure is called to add a local directory to the search path used by 'use-modules' or 'load', that will have effect for all other tasks.

Other thread safety points

Leaving aside what has been said above, there are a few other issues to keep in mind if executing scheme code in more than one thread.

First, the initialization of guile < 2.0.10 is not thread safe. One thread needs to have called Extension::exec() or Extension::exec_shared() once and returned before any other threads call the function. This can be achieved by the simple expedient of executing the statement:

and waiting for it to return before any tasks are added to a TaskManager object running more than one thread. This issue is fixed in guile-2.0.10. However there is a further snag. Certain aspects of guile module loading are not thread safe. One way around this is to load all the modules that tasks may use in advance, by loading the modules in the preamble of the above statement (or to have that statement execute a file which loads the modules). If that is done, it should be fine afterwards to run Extension::exec() (or Extension::exec_shared() if clashing top level definitions are avoided as mentioned above) on a TaskManager object running any number of threads, or on a Thread::Future object or std::async() task. (However, note that if using Extension::exec() the modules would need to be reloaded in each task in order to make them visible to the task, but that would be done safely if they have previously been loaded in another task.)

If a C++ program is to run guile tasks on a TaskManager object having a maximum thread count greater than one (or in more than one thread in some other way), one other point should be noted. When a scheme file is executed for the first time by a user by being passed as the second argument of Extension::exec() (or by having 'load' applied to it in some other way), it will be compiled into byte code, the byte code will then be cached on the file system for that and subsequent calls, and the byte code then executed. Bad things might happen if concurrent calls to Extension::exec(), or to the 'load' or 'use-modules' procedures, are made in respect of the same scheme file for the "first" time, if there might be a race as to which of them is the "first" call in respect of the file: that is, if it causes two or more threads to try to compile the same file into byte code concurrently. This is only an issue the first time a particular user executes a scheme file, and can be avoided (amongst other ways) by having the C++ program concerned pre-compile the relevant scheme file before Extension::exec() or Extension::exec_shared() is first called, by means of the 'guild compile [filename]' command. The following gives more information about compilation: Compiling Scheme Code

Licence

The c++-gtk-utils library (and this c++-gtk-utils/extension.h header file) follows glib and GTK+ by being released under the LGPL version 2.1 or later. libguile is released under the LGPL version 3 or later. The c++-gtk-utils library object code does not link to libguile, nor does it incorporate anything in the c++-gtk-utils/extension.h header. Instead c++-gtk-utils/extension.h contains all its code as a separate unlinked header for any program which wants to include it (this is partly because some of it comprises template functions).

There are two consequences. If you want to use Extension::exec() or Extension::exec_shared(), the program which calls it will need to link itself explicitly with libguile as well as c++-gtk-utils, and to do that will need to use pkg-config to obtain libguile's cflags and libs particulars (its pkg-config file is guile-2.0.pc, guile-2.2.pc or guile-3.0.pc). This library does NOT do that for you. Secondly, by linking with libguile you will be governed by the LGPL version 3 or later, instead of the LGPL version 2.1 or later, with respect to that linking. That's fine (there is nothing wrong with the LGPL version 3 and this library permits that) but you should be aware of it. The scheme code in guile's scheme level modules is also in the main released under the LGPL version 3 or later ("in the main" because readline.scm, comprised in the readline module, is released under the GPL version 3 or later).

Configuration

By default, when the c++-gtk-utils library is configured, configuration will first look for guile-3.0 >= 3.0.0, then if it does not find that it will look for guile-2.2 >= 2.1.3, then if it does not find that it will look for guile-2.0 >= 2.0.2, and then if it finds none it will disable guile support; and the library header files will then be set up appropriately. guile-3.0, guile-2.2 or guile-2.0 can be specifically picked with the --with-guile=3.0, --with-guile=2.2 or --with-guile=2.0 configuration options respectively. Guile support can be omitted with the --with-guile=no option.

However, as mentioned under "Licence" above, any program using Extension::exec() or Extension::exec_shared() must link itself explicitly with libguile via either guile-2.0.pc (for guile-2.0), guile-2.2.pc (for guile-2.2) or guile-3.0.pc (for guile-3.0). Programs should use whichever of those is the one for which c++-gtk-utils was configured. If you get link-time messages from a program about being unable to link to scm_dynwind_block_asyncs(), then there has been a version mismatch. If you get link-time messages about being unable to link to Cgu::Extension::init_mutex() or Cgu::Extension::get_user_module_mutex() then c++-gtk-utils has not been configured to offer guile support.

Custom translators

Any function or callable object which translates from an opaque SCM value to a suitable C++ representation can be passed as the third argument of Extension::exec() or Extension::exec_shared(). C++ type deduction on template resolution will take care of everything else. The translator can execute any functions offered by libguile, because when the translator is run the program is still in guile mode. The fulsome guile documentation sets out the libguile functions which are callable in C/C++ code.

The first call in a custom translator should normally be to the Extension::rethrow_guile_exception() function. This function tests whether a guile exception arose in executing the scheme file, and throws a C++ exception if it did. The preformed translators in extension.h provide worked examples of how a custom translator might be written.

If something done in a custom translator were to raise a guile exception, the library implementation would handle it and a C++ exception would be generated in its place in Extension::exec() or Extension::exec_shared(). However, a custom translator should not allow a guile exception arising from calls to libguile made by it to exit a C++ scope in which the translator has constructed a local C++ object which is not trivially destructible: that would give rise to undefined behaviour, with the likely result that the C++ object's destructor would not be called. One approach to this (adopted in the preformed translators) is to allocate on free store all local C++ objects to be constructed in the translator which are not trivially destructible, and to manage their lifetimes manually using local C++ try/catch blocks rather than RAII, with dynwind unwind handlers to release memory were there to be a guile exception (but note that no C++ exception should transit out of a scm_dynwind_begin()/scm_dynwind_end() pair). It is also a good idea to test for any condition which might cause a guile exception to be raised in the translator in the first place, and throw a C++ exception beforehand. Then the only condition which might cause a guile exception to occur in the translator is an out-of-memory condition, which is highly improbable in a translator as the translator is run after the guile task has completed. Heap exhaustion in such a case probably spells doom for the program concerned anyway, if it has other work to do.

Note also that code in a custom translator should not store guile SCM objects (which are pointers to guile scheme objects) in memory blocks allocated by malloc() or the new expression, or they will not be seen by the garbage collector used by libguile (which is the gc library) and therefore may be prematurely deallocated. To keep such items alive in custom translators, SCM variables should be kept as local variables or parameter names in functions (and so stored on the stack or in registers, where they will be seen by the garbage collector), or in memory allocated with scm_gc_malloc(), where they will also be seen by the garbage collector.

Scheme

If you want to learn more about scheme, these are useful sources:

Chapter 3 of the Guile Manual (the rest of the manual is also good reading).

The Scheme Programming Language, 4th edition

Function Documentation

◆ any_to_void()

void* Cgu::Extension::any_to_void ( SCM  scm)
inline

A translator function which can be passed to the third argument of Extension::exec() or Extension::exec_shared(). It disregards the scheme value passed to it except to trap any guile exception thrown by the scheme task and rethrow it as a C++ exception, and returns a NULL void* object. It is thread safe, but see the comments above about the thread safety of Extension::exec() and Extension::exec_shared().

It is mainly intended for use where the scheme script is executed for its side effects, perhaps for I/O, and any communication necessary is done by guile exceptions.

Parameters
scmAn opaque guile SCM object representing the value to which the extension file passed to Extension::exec() or Extension::exec_shared() evaluated, which is ignored.
Returns
A NULL void* object.
Exceptions
std::bad_allocThis function might throw std::bad_alloc if memory is exhausted and the system throws in that case.
Cgu::Extension::GuileExceptionThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() caused a guile exception to be thrown. Cgu::Extension::GuileException::what() will give particulars of the guile exception thrown, in UTF-8 encoding.
Note
No native guile exception will arise in this function and so cause guile to jump out of it if no guile out-of-memory condition occurs (given that this function is called after a guile extension task has completed, such a condition is very improbable). If such an exception were to arise, the implementation would handle it and a C++ exception would be generated in its place in Extension::exec() or Extension::exec_shared().

Since 2.0.22

◆ exception_to_string()

SCM Cgu::Extension::exception_to_string ( SCM  key,
SCM  args 
)
inline

This function is called by Extension::rethrow_guile_exception() where the scheme code executed by Extension::exec() or Extension::exec_shared() has exited with a guile exception. It converts the raw guile exception information represented by the 'key' and 'args' arguments of a guile catch handler to a more readable form. It is made available as part of the public interface so that any custom translators can also use it if they choose to provide their own catch expressions. This function does not throw any C++ exceptions. No native guile exception will arise in this function and so cause guile to jump out of it assuming no guile out-of-memory condition occurs (and given that this function is called after a guile extension task has completed, such a condition is very improbable). It is thread safe, but see the comments above about the thread safety of Extension::exec() and Extension::exec_shared().

Parameters
keyAn opaque guile SCM object representing a symbol comprising the 'key' argument of the exception handler of a guile catch expression.
argsAn opaque guile SCM object representing a list comprising the 'args' argument of the exception handler of a guile catch expression.
Returns
An opaque guile SCM object representing a guile string.

Since 2.0.22

◆ exec()

template<class Translator >
auto Cgu::Extension::exec ( const std::string &  preamble,
const std::string &  file,
Translator  translator 
) -> typename std::result_of<Translator(SCM)>::type

This function executes scheme code on the guile VM within a C++ program using this library. See the introductory remarks above for its potential uses, about the thread safety of this function, and about the use of the TaskManager::exec_shared() as an alternative.

The first argument to this function is a preamble, which can be used to pass top level definitions to the scheme code (in other words, for argument passing). It's second argument is the filename (with path) of the file containing the scheme code to be executed. It's third argument is a translator, which will convert the value to which the scheme code evaluates (in C++ terms, its return value) to a suitable C++ representation. Preformed translators are provided by this library to translate from scheme's integers, real numbers and strings to C++ longs, doubles and strings respectively, and from any uniform lists of these to C++ vectors of the corresponding type. There is also a translator for void return types. See the introductory remarks above for more information about translators.

Any native guile exceptions thrown by the code executed by this function (and by any code which it calls) are converted and rethrown as C++ exceptions.

The scheme file can call other scheme code, and load modules, in the ordinary way. Thus, this function can execute any scheme code which guile can execute as a program, and the programmer can (if wanted) act on its return value in the C++ code which invokes it.

Thread cancellation is blocked for the thread in which this function executes until this function returns.

Parameters
preambleScheme code such as top level definitions to be seen by the code in the file to be executed. This is mainly intended for argument passing, but can comprise any valid scheme code. It can also be empty (you can pass ""). Any string literals must be in UTF-8 encoding.
fileThe file which is to be executed on the guile VM. This should include the full pathname or a pathname relative to the current directory. The contents of the file, and in particular any string literals in it, must be in UTF-8 encoding. The filename and path must also be given in UTF-8 encoding, even if the local filename encoding is something different: guile will convert the UTF-8 name which it is given to its own internal string encoding using unicode code points, and then convert that to locale encoding on looking up the filename. However sticking to ASCII for filenames and paths (which is always valid UTF-8) will maximise portability. The file name can be empty (you can pass ""), in which case only the preamble will be evaluated (but for efficiency reasons any complex code not at the top level should be included in the file rather than in the preamble).
translatorThe function or callable object which will convert the value to which the scheme code evaluates to a C++ representation which will be returned by this function. The translator should take a single argument comprising an opaque guile object of type SCM, and return the C++ representation for it.
Returns
The C++ representation returned by the translator.
Exceptions
std::bad_allocThis function might throw std::bad_alloc if memory is exhausted and the system throws in that case.
Cgu::Extension::GuileExceptionThis exception will be thrown if the scheme code in 'file' (or called by it) throws a guile exception. Cgu::Extension::GuileException::what() will give particulars of the guile exception thrown, in UTF-8 encoding.
Cgu::Extension::ReturnValueErrorThis exception will be thrown if the code in 'file' does not evaluate to the type expected by the translator.
Cgu::Extension::WrapperErrorThis exception will be thrown if a custom translator throws a native guile exception or a C++ exception not comprising Extension::GuileException or Extension::ReturnValueError, one of the preformed translators throws std::bad_alloc or encounters a guile out-of-memory exception, one of the preformed list translators encounters an input list exceeding SIZE_MAX in length, assigning to an internal exception description string throws std::bad_alloc, or evaluation of the preamble throws a native guile exception.

Since 2.0.22

◆ exec_shared()

template<class Translator >
auto Cgu::Extension::exec_shared ( const std::string &  preamble,
const std::string &  file,
Translator  translator 
) -> typename std::result_of<Translator(SCM)>::type

This function executes scheme code on the guile VM within a C++ program using this library. See the introductory remarks above for its potential uses, about the thread safety of this function, and about the use of the TaskManager::exec() as an alternative.

The first argument to this function is a preamble, which can be used to pass top level definitions to the scheme code (in other words, for argument passing). It's second argument is the filename (with path) of the file containing the scheme code to be executed. It's third argument is a translator, which will convert the value to which the scheme code evaluates (in C++ terms, its return value) to a suitable C++ representation. Preformed translators are provided by this library to translate from scheme's integers, real numbers and strings to C++ longs, doubles and strings respectively, and from any uniform lists of these to C++ vectors of the corresponding type. There is also a translator for void return types. See the introductory remarks above for more information about translators.

Any native guile exceptions thrown by the code executed by this function (and by any code which it calls) are converted and rethrown as C++ exceptions.

The scheme file can call other scheme code, and load modules, in the ordinary way. Thus, this function can execute any scheme code which guile can execute as a program, and the programmer can (if wanted) act on its return value in the C++ code which invokes it.

Thread cancellation is blocked for the thread in which this function executes until this function returns.

Parameters
preambleScheme code such as top level definitions to be seen by the code in the file to be executed. This is mainly intended for argument passing, but can comprise any valid scheme code. It can also be empty (you can pass ""). Any string literals must be in UTF-8 encoding.
fileThe file which is to be executed on the guile VM. This should include the full pathname or a pathname relative to the current directory. The contents of the file, and in particular any string literals in it, must be in UTF-8 encoding. The filename and path must also be given in UTF-8 encoding, even if the local filename encoding is something different: guile will convert the UTF-8 name which it is given to its own internal string encoding using unicode code points, and then convert that to locale encoding on looking up the filename. However sticking to ASCII for filenames and paths (which is always valid UTF-8) will maximise portability. The file name can be empty (you can pass ""), in which case only the preamble will be evaluated.
translatorThe function or callable object which will convert the value to which the scheme code evaluates to a C++ representation which will be returned by this function. The translator should take a single argument comprising an opaque guile object of type SCM, and return the C++ representation for it.
Returns
The C++ representation returned by the translator.
Exceptions
std::bad_allocThis function might throw std::bad_alloc if memory is exhausted and the system throws in that case.
Cgu::Extension::GuileExceptionThis exception will be thrown if the scheme code in 'file' (or called by it) throws a guile exception. Cgu::Extension::GuileException::what() will give particulars of the guile exception thrown, in UTF-8 encoding.
Cgu::Extension::ReturnValueErrorThis exception will be thrown if the code in 'file' does not evaluate to the type expected by the translator.
Cgu::Extension::WrapperErrorThis exception will be thrown if a custom translator throws a native guile exception or a C++ exception not comprising Extension::GuileException or Extension::ReturnValueError, one of the preformed translators throws std::bad_alloc or encounters a guile out-of-memory exception, one of the preformed list translators encounters an input list exceeding SIZE_MAX in length, assigning to an internal exception description string throws std::bad_alloc, or evaluation of the preamble throws a native guile exception.

Since 2.0.24

◆ integer_to_long()

long Cgu::Extension::integer_to_long ( SCM  scm)
inline

A translator function which can be passed to the third argument of Extension::exec() or Extension::exec_shared(). It converts from a scheme integer to a C++ representation of long. It is thread safe, but see the comments above about the thread safety of Extension::exec() and Extension::exec_shared().

Parameters
scmAn opaque guile SCM object representing the value to which the extension file passed to Extension::exec() or Extension::exec_shared() evaluated, where that value is an integer.
Returns
The C++ long representation.
Exceptions
std::bad_allocThis function might throw std::bad_alloc if memory is exhausted and the system throws in that case.
Cgu::Extension::GuileExceptionThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() caused a guile exception to be thrown. Cgu::Extension::GuileException::what() will give particulars of the guile exception thrown, in UTF-8 encoding.
Cgu::Extension::ReturnValueErrorThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() does not evaluate to the type expected by the translator, or it is out of range for a long.
Note
No native guile exception will arise in this function and so cause guile to jump out of it if no guile out-of-memory condition occurs (given that this function is called after a guile extension task has completed, such a condition is very improbable). If such an exception were to arise, the implementation would handle it and a C++ exception would be generated in its place in Extension::exec() or Extension::exec_shared().

Since 2.0.22

◆ list_to_vector_double()

std::vector<double> Cgu::Extension::list_to_vector_double ( SCM  scm)
inline

A translator function which can be passed to the third argument of Extension::exec() or Extension::exec_shared(). It converts from a homogeneous scheme list of real numbers to a C++ representation of std::vector<double>. It is thread safe, but see the comments above about the thread safety of Extension::exec() and Extension::exec_shared().

Parameters
scmAn opaque guile SCM object representing the value to which the extension file passed to Extension::exec() or Extension::exec_shared() evaluated, where that value is a homogeneous list of real numbers.
Returns
The std::vector<double> representation.
Exceptions
std::bad_allocThis function might throw std::bad_alloc if memory is exhausted and the system throws in that case, or if the length of the input list exceeds std::vector::max_size().
Cgu::Extension::GuileExceptionThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() caused a guile exception to be thrown. Cgu::Extension::GuileException::what() will give particulars of the guile exception thrown, in UTF-8 encoding.
Cgu::Extension::ReturnValueErrorThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() does not evaluate to the type expected by the translator, or it is out of range for a double.
Note
1. Prior to version 2.0.25, this translator had a bug which caused an out-of-range Cgu::Extension::ReturnValueError to be thrown if any of the numbers in the list to which the scheme code in the extension file evaluated was 0.0 or a negative number. This was fixed in version 2.0.25.
2. No native guile exception will arise in this function and so cause guile to jump out of it unless a guile out-of-memory condition occurs (given that this function is called after a guile extension task has completed, such a condition is very improbable) or the length of the input list exceeds SIZE_MAX (the maximum value of std::size_t). If such an exception were to arise, the implementation would handle it and a C++ exception would be generated in its place in Extension::exec() or Extension::exec_shared().

Since 2.0.22

◆ list_to_vector_long()

std::vector<long> Cgu::Extension::list_to_vector_long ( SCM  scm)
inline

A translator function which can be passed to the third argument of Extension::exec() or Extension::exec_shared(). It converts from a homogeneous scheme list of integers to a C++ representation of std::vector<long>. It is thread safe, but see the comments above about the thread safety of Extension::exec() and Extension::exec_shared().

Parameters
scmAn opaque guile SCM object representing the value to which the extension file passed to Extension::exec() or Extension::exec_shared() evaluated, where that value is a homogeneous list of integers.
Returns
The std::vector<long> representation.
Exceptions
std::bad_allocThis function might throw std::bad_alloc if memory is exhausted and the system throws in that case, or if the length of the input list exceeds std::vector::max_size().
Cgu::Extension::GuileExceptionThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() caused a guile exception to be thrown. Cgu::Extension::GuileException::what() will give particulars of the guile exception thrown, in UTF-8 encoding.
Cgu::Extension::ReturnValueErrorThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() does not evaluate to the type expected by the translator, or it is out of range for a long.
Note
No native guile exception will arise in this function and so cause guile to jump out of it unless a guile out-of-memory condition occurs (given that this function is called after a guile extension task has completed, such a condition is very improbable) or the length of the input list exceeds SIZE_MAX (the maximum value of std::size_t). If such an exception were to arise, the implementation would handle it and a C++ exception would be generated in its place in Extension::exec() or Extension::exec_shared().

Since 2.0.22

◆ list_to_vector_string()

std::vector<std::string> Cgu::Extension::list_to_vector_string ( SCM  scm)
inline

A translator function which can be passed to the third argument of Extension::exec() or Extension::exec_shared(). It converts from a homogeneous scheme list of strings to a C++ representation of std::vector<std::string>. It is thread safe, but see the comments above about the thread safety of Extension::exec() and Extension::exec_shared().

The returned strings will be in UTF-8 encoding.

Note that the first string in the returned list must not be "***cgu-guile-exception***": that string is reserved to the implementation.

Parameters
scmAn opaque guile SCM object representing the value to which the extension file passed to Extension::exec() or Extension::exec_shared() evaluated, where that value is a homogeneous list of strings.
Returns
The std::vector<std::string> representation.
Exceptions
std::bad_allocThis function might throw std::bad_alloc if memory is exhausted and the system throws in that case, or if the length of the input list exceeds std::vector::max_size().
Cgu::Extension::GuileExceptionThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() caused a guile exception to be thrown. Cgu::Extension::GuileException::what() will give particulars of the guile exception thrown, in UTF-8 encoding.
Cgu::Extension::ReturnValueErrorThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() does not evaluate to the type expected by the translator.
Note
No native guile exception will arise in this function and so cause guile to jump out of it unless a guile out-of-memory condition occurs (given that this function is called after a guile extension task has completed, such a condition is very improbable) or the length of the input list exceeds SIZE_MAX (the maximum value of std::size_t). If such an exception were to arise, the implementation would handle it and a C++ exception would be generated in its place in Extension::exec() or Extension::exec_shared().

Since 2.0.22

◆ real_to_double()

double Cgu::Extension::real_to_double ( SCM  scm)
inline

A translator function which can be passed to the third argument of Extension::exec() or Extension::exec_shared(). It converts from a scheme real number to a C++ representation of double. It is thread safe, but see the comments above about the thread safety of Extension::exec() and Extension::exec_shared().

Parameters
scmAn opaque guile SCM object representing the value to which the extension file passed to Extension::exec() or Extension::exec_shared() evaluated, where that value is a real number.
Returns
The C++ double representation.
Exceptions
std::bad_allocThis function might throw std::bad_alloc if memory is exhausted and the system throws in that case.
Cgu::Extension::GuileExceptionThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() caused a guile exception to be thrown. Cgu::Extension::GuileException::what() will give particulars of the guile exception thrown, in UTF-8 encoding.
Cgu::Extension::ReturnValueErrorThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() does not evaluate to the type expected by the translator, or it is out of range for a double.
Note
1. Prior to version 2.0.25, this translator had a bug which caused an out-of-range Cgu::Extension::ReturnValueError to be thrown if the scheme code in the extension file evaluated to 0.0 or a negative number. This was fixed in version 2.0.25.
2. No native guile exception will arise in this function and so cause guile to jump out of it if no guile out-of-memory condition occurs (given that this function is called after a guile extension task has completed, such a condition is very improbable). If such an exception were to arise, the implementation would handle it and a C++ exception would be generated in its place in Extension::exec() or Extension::exec_shared().

Since 2.0.22

◆ rethrow_guile_exception()

void Cgu::Extension::rethrow_guile_exception ( SCM  scm)
inline

This function tests whether a guile exception arose in executing a scheme extension file, and throws Cgu::Extension::GuileException if it did. It is intended for use by custom translators, as the first thing the translator does. It is thread safe, but see the comments above about the thread safety of Extension::exec() and Extension::exec_shared().

Parameters
scmAn opaque guile SCM object representing the value to which the extension file passed to Extension::exec() or Extension::exec_shared() evaluated.
Exceptions
std::bad_allocThis function might throw std::bad_alloc if memory is exhausted and the system throws in that case.
Cgu::Extension::GuileExceptionThis exception will be thrown if the scheme code executed in the extension file passed to Extension::exec() or Extension::exec_shared() threw a guile exception. Cgu::Extension::GuileException::what() will give particulars of the guile exception thrown, in UTF-8 encoding.
Note
No native guile exception will arise in this function and so cause guile to jump out of it if no guile out-of-memory condition occurs (given that this function is called after a guile extension task has completed, such a condition is very improbable).

Since 2.0.22

◆ string_to_string()

std::string Cgu::Extension::string_to_string ( SCM  scm)
inline

A translator function which can be passed to the third argument of Extension::exec() or Extension::exec_shared(). It converts from a scheme string to a C++ representation of std::string. It is thread safe, but see the comments above about the thread safety of Extension::exec() and Extension::exec_shared().

The returned string will be in UTF-8 encoding.

Parameters
scmAn opaque guile SCM object representing the value to which the extension file passed to Extension::exec() or Extension::exec_shared() evaluated, where that value is a string.
Returns
The std::string representation.
Exceptions
std::bad_allocThis function might throw std::bad_alloc if memory is exhausted and the system throws in that case.
Cgu::Extension::GuileExceptionThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() caused a guile exception to be thrown. Cgu::Extension::GuileException::what() will give particulars of the guile exception thrown, in UTF-8 encoding.
Cgu::Extension::ReturnValueErrorThis exception will be thrown if the scheme code in the extension file passed to Extension::exec() or Extension::exec_shared() does not evaluate to the type expected by the translator.
Note
No native guile exception will arise in this function and so cause guile to jump out of it if no guile out-of-memory condition occurs (given that this function is called after a guile extension task has completed, such a condition is very improbable). If such an exception were to arise, the implementation would handle it and a C++ exception would be generated in its place in Extension::exec() or Extension::exec_shared().

Since 2.0.22

Cgu::Extension::list_to_vector_string
std::vector< std::string > list_to_vector_string(SCM scm)
Definition: extension.h:1322
Cgu::Extension::string_to_string
std::string string_to_string(SCM scm)
Definition: extension.h:1566
Cgu::Callback::to_unique
std::unique_ptr< const CallbackArg< T... > > to_unique(const CallbackArg< T... > *cb)
Definition: callback.h:719
Cgu
Definition: application.h:44
Cgu::Extension::any_to_void
void * any_to_void(SCM scm)
Definition: extension.h:1613
Cgu::Extension::exec_shared
auto exec_shared(const std::string &preamble, const std::string &file, Translator translator) -> typename std::result_of< Translator(SCM)>::type
Definition: extension.h:1794
Cgu::Thread::TaskManager
A thread-pool class for managing tasks in multi-threaded programs.
Definition: task_manager.h:462