unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Prototype for C++-compatible Guile Exceptions.
@ 2015-07-14 18:07 Taahir Ahmed
  2015-07-14 18:07 ` [PATCH 1/3] Support C++ source files, use -fexceptions Taahir Ahmed
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Taahir Ahmed @ 2015-07-14 18:07 UTC (permalink / raw)
  To: guile-devel

I'm posting these patches to feel out the likelihood of this approach to
C++ exception compatibility ever getting adopted into Guile.  They still
need some work in terms of function documentation, and one test failure.

----------------------------------------------------------------------

Currently, the use of libguile functions from C++ is fraught with
danger.  C++ destructors are not triggered by guile exceptions, and the
dynwind mechanism is ill-suited for application to C++ data structures
(in particular, STL structures).

In my experience, writing a C++ function that takes data from guile code
in a truly safe manner roughly doubles the required amount of code,
because of the generally-required pattern:

    // ...

    // Some code to check that a SCM really is an int.
    int dummy = scm_to_int(my_scm);

    // Below this point, no guile exceptions may be thrown.

    // Now, we can create a std::vector, or what-have-you, and put our
    // int into it.

    std::vector<int> my_vector;
    my_vector.push_back(scm_to_int(my_scm));

    // ...

This sequence of patches addresses this shortcoming by using hidden C++
exceptions to perform the stack unwinding when a guile exception is
thrown, so that the pre-checking demonstrated above is not needed.

# How is this implemented?

This sequence of patches does four things:

  - Enables autotools C++ support.

  - Adds -fexceptions to the compiler command line to enable C++
    exceptions to traverse C stack frames.

  - Adds extern "C" guards to the internal libguile headers.

  - Adds a single C++ source file to libguile that contains set/longjmp
    workalikes for prompt and exception handling.  Prompt and
    exception-related uses of set/longjmp are replaced with these
    functions. (This is the third patch, and the real meat of the work).

# What are the downsides of this prototype implementation?

The use of -fexceptions and a C++ source file limit the choice of
compiler.  GCC, Clang, and ICC should be fine.  I have no idea about
some of the more esoteric compilers.

On most platforms, -fexceptions entails some space overhead.  In my
testing, libguile gets bumped from 4.8 MiB to about 5 MiB.

The last two test cases in test-out-of-memory ("the kicker" and "ouch")
fail.  I'm still investigating the root cause.  All other tests pass.




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] Support C++ source files, use -fexceptions.
  2015-07-14 18:07 Prototype for C++-compatible Guile Exceptions Taahir Ahmed
@ 2015-07-14 18:07 ` Taahir Ahmed
  2015-07-14 18:07 ` [PATCH 2/3] Add C++ extern "C" guards to internal headers Taahir Ahmed
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Taahir Ahmed @ 2015-07-14 18:07 UTC (permalink / raw)
  To: guile-devel

-fexceptions allows C++ exceptions to pass through C stack frames.
---
 configure.ac         | 1 +
 libguile/Makefile.am | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 19e00d8..78cbffc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,6 +66,7 @@ AC_LIBTOOL_WIN32_DLL
 
 AC_PROG_INSTALL
 AC_PROG_CC
+AC_PROG_CXX
 gl_EARLY
 AC_PROG_CPP
 AC_PROG_SED
diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index 8302a18..cc88215 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -38,7 +38,8 @@ DEFAULT_INCLUDES =
 AM_CPPFLAGS = -DBUILDING_LIBGUILE=1 -I$(top_srcdir) -I$(top_builddir) \
 	      -I$(top_srcdir)/lib -I$(top_builddir)/lib $(LIBFFI_CFLAGS)
 
-AM_CFLAGS = $(GCC_CFLAGS) $(CFLAG_VISIBILITY)
+AM_CFLAGS = -fexceptions $(GCC_CFLAGS) $(CFLAG_VISIBILITY)
+AM_CXXFLAGS = $(GCC_CFLAGS) $(CFLAG_VISIBILITY)
 
 ## The Gnulib Libtool archive.
 gnulib_library = $(top_builddir)/lib/libgnu.la
@@ -113,10 +114,12 @@ guile_filter_doc_snarfage$(EXEEXT): $(guile_filter_doc_snarfage_OBJECTS) $(guile
 
 guile_SOURCES = guile.c
 guile_CFLAGS = $(GUILE_CFLAGS) $(AM_CFLAGS)
+guile_CXXFLAGS = $(GUILE_CXXFLAGS) $(AM_CXXFLAGS)
 guile_LDADD = libguile-@GUILE_EFFECTIVE_VERSION@.la
 guile_LDFLAGS = $(GUILE_CFLAGS)
 
 libguile_@GUILE_EFFECTIVE_VERSION@_la_CFLAGS = $(GUILE_CFLAGS) $(AM_CFLAGS)
+libguile_@GUILE_EFFECTIVE_VERSION@_la_CXXFLAGS = $(GUILE_CXXFLAGS) $(AM_CXXFLAGS)
 
 libguile_@GUILE_EFFECTIVE_VERSION@_la_SOURCES =				\
 	alist.c					\
-- 
2.3.6




^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] Add C++ extern "C" guards to internal headers.
  2015-07-14 18:07 Prototype for C++-compatible Guile Exceptions Taahir Ahmed
  2015-07-14 18:07 ` [PATCH 1/3] Support C++ source files, use -fexceptions Taahir Ahmed
@ 2015-07-14 18:07 ` Taahir Ahmed
  2015-07-14 19:36   ` Andreas Rottmann
  2015-07-15  3:40 ` [PATCH 3/3] Implement Guile exceptions with C++ exceptions Taahir Ahmed
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Taahir Ahmed @ 2015-07-14 18:07 UTC (permalink / raw)
  To: guile-devel

---
 libguile/__scm.h               |  8 ++++++++
 libguile/_scm.h                | 10 ++++++++++
 libguile/alist.h               |  8 ++++++++
 libguile/arbiters.h            |  8 ++++++++
 libguile/array-handle.h        |  7 +++++++
 libguile/array-map.h           |  8 ++++++++
 libguile/arrays.h              |  8 ++++++++
 libguile/async.h               |  8 ++++++++
 libguile/backtrace.h           |  8 ++++++++
 libguile/bdw-gc.h              |  7 +++++++
 libguile/bitvectors.h          |  8 ++++++++
 libguile/boolean.h             |  8 ++++++++
 libguile/bytevectors.h         |  7 +++++++
 libguile/chars.h               |  8 ++++++++
 libguile/continuations.h       |  9 +++++++++
 libguile/control.h             |  6 ++++++
 libguile/debug-malloc.h        |  8 ++++++++
 libguile/debug.h               |  9 +++++++++
 libguile/deprecated.h          |  8 ++++++++
 libguile/deprecation.h         |  8 ++++++++
 libguile/dynl.h                |  8 ++++++++
 libguile/dynstack.h            |  8 ++++++++
 libguile/dynwind.h             |  7 +++++++
 libguile/elf.h                 |  7 +++++++
 libguile/eq.h                  |  8 ++++++++
 libguile/error.h               |  8 ++++++++
 libguile/evalext.h             |  8 ++++++++
 libguile/expand.h              |  6 ++++++
 libguile/extensions.h          |  8 ++++++++
 libguile/feature.h             |  8 ++++++++
 libguile/filesys.h             |  8 ++++++++
 libguile/finalizers.h          |  8 ++++++++
 libguile/fluids.h              |  7 +++++++
 libguile/foreign-object.h      |  6 ++++++
 libguile/foreign.h             |  8 ++++++++
 libguile/fports.h              |  7 +++++++
 libguile/frames.h              |  8 ++++++++
 libguile/gc-inline.h           | 13 +++++++++++++
 libguile/gc.h                  |  8 ++++++++
 libguile/generalized-arrays.h  |  7 +++++++
 libguile/generalized-vectors.h |  8 ++++++++
 libguile/gettext.h             |  8 ++++++++
 libguile/goops.h               |  8 ++++++++
 libguile/gsubr.h               |  7 +++++++
 libguile/guardians.h           |  8 ++++++++
 libguile/hash.h                |  8 ++++++++
 libguile/hashtab.h             |  8 ++++++++
 libguile/hooks.h               |  8 ++++++++
 libguile/i18n.h                |  7 +++++++
 libguile/init.h                |  9 +++++++++
 libguile/inline.h              |  9 +++++++++
 libguile/instructions.h        |  8 ++++++++
 libguile/ioext.h               |  8 ++++++++
 libguile/iselect.h             |  8 ++++++++
 libguile/keywords.h            |  8 ++++++++
 libguile/libgettext.h          | 16 ++++++++++++++++
 libguile/list.h                |  8 ++++++++
 libguile/load.h                |  8 ++++++++
 libguile/loader.h              |  8 ++++++++
 libguile/macros.h              |  7 +++++++
 libguile/mallocs.h             |  9 +++++++++
 libguile/memoize.h             |  7 +++++++
 libguile/modules.h             |  8 ++++++++
 libguile/net_db.h              |  8 ++++++++
 libguile/null-threads.h        |  7 +++++++
 libguile/numbers.h             | 16 ++++++++++++++++
 libguile/objprop.h             |  8 ++++++++
 libguile/options.h             |  8 ++++++++
 libguile/pairs.h               |  9 +++++++++
 libguile/poll.h                |  8 ++++++++
 libguile/ports-internal.h      |  8 ++++++++
 libguile/ports.h               |  8 ++++++++
 libguile/posix.h               |  7 +++++++
 libguile/print.h               |  9 +++++++++
 libguile/private-options.h     |  8 ++++++++
 libguile/procprop.h            |  8 ++++++++
 libguile/procs.h               |  8 ++++++++
 libguile/programs.h            |  8 ++++++++
 libguile/promises.h            |  7 +++++++
 libguile/pthread-threads.h     |  8 ++++++++
 libguile/r6rs-ports.h          |  8 ++++++++
 libguile/random.h              |  9 +++++++++
 libguile/rdelim.h              |  8 ++++++++
 libguile/read.h                |  9 +++++++++
 libguile/regex-posix.h         |  8 ++++++++
 libguile/root.h                |  8 ++++++++
 libguile/rw.h                  |  8 ++++++++
 libguile/scmsigs.h             |  8 ++++++++
 libguile/script.h              |  9 +++++++++
 libguile/simpos.h              |  8 ++++++++
 libguile/smob.h                |  7 +++++++
 libguile/snarf.h               |  8 ++++++++
 libguile/socket.h              |  8 ++++++++
 libguile/sort.h                |  8 ++++++++
 libguile/srcprop.h             |  7 +++++++
 libguile/srfi-1.h              |  8 ++++++++
 libguile/srfi-13.h             |  8 ++++++++
 libguile/srfi-14.h             |  8 ++++++++
 libguile/srfi-4.h              |  8 ++++++++
 libguile/srfi-60.h             |  8 ++++++++
 libguile/stackchk.h            |  8 ++++++++
 libguile/stacks.h              |  8 ++++++++
 libguile/stime.h               |  8 ++++++++
 libguile/strings.h             |  8 ++++++++
 libguile/strorder.h            |  8 ++++++++
 libguile/strports.h            |  8 ++++++++
 libguile/struct.h              |  8 ++++++++
 libguile/symbols.h             |  9 +++++++++
 libguile/tags.h                |  8 ++++++++
 libguile/threads.h             |  8 ++++++++
 libguile/throw.h               |  8 ++++++++
 libguile/trees.h               |  8 ++++++++
 libguile/unicode.h             |  8 ++++++++
 libguile/uniform.h             |  7 +++++++
 libguile/validate.h            |  8 ++++++++
 libguile/values.h              |  8 ++++++++
 libguile/variable.h            |  8 ++++++++
 libguile/vectors.h             |  8 ++++++++
 libguile/vm-builtins.h         |  8 ++++++++
 libguile/vm-expand.h           |  8 ++++++++
 libguile/vm.h                  |  8 ++++++++
 libguile/vports.h              |  8 ++++++++
 libguile/weak-set.h            |  8 ++++++++
 libguile/weak-table.h          |  8 ++++++++
 libguile/weak-vector.h         |  7 +++++++
 libguile/win32-uname.h         |  8 ++++++++
 126 files changed, 1017 insertions(+)

diff --git a/libguile/__scm.h b/libguile/__scm.h
index 31e3952..1967069 100644
--- a/libguile/__scm.h
+++ b/libguile/__scm.h
@@ -53,6 +53,10 @@
 /* What did the configure script discover about the outside world?  */
 #include "libguile/scmconfig.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* {Compiler hints}
@@ -523,6 +527,10 @@ typedef long SCM_STACKITEM;
 # define SCM_THREAD_LOCAL
 #endif
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM___SCM_H */
 
 /*
diff --git a/libguile/_scm.h b/libguile/_scm.h
index 97ddaf2..183fe50 100644
--- a/libguile/_scm.h
+++ b/libguile/_scm.h
@@ -134,6 +134,12 @@
 
 \f
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+\f
+
 #ifndef min
 #define min(A, B) ((A) <= (B) ? (A) : (B))
 #endif
@@ -278,6 +284,10 @@ void scm_ia64_longjmp (scm_i_jmp_buf *, int);
 #define SCM_OBJCODE_MACHINE_VERSION_STRING                              \
   SCM_OBJCODE_ENDIANNESS "-" SCM_OBJCODE_WORD_SIZE "-" SCM_OBJCODE_VERSION_STRING
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM__SCM_H */
 
 /*
diff --git a/libguile/alist.h b/libguile/alist.h
index 77c5656..0faea9f 100644
--- a/libguile/alist.h
+++ b/libguile/alist.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_acons (SCM w, SCM x, SCM y);
@@ -45,6 +49,10 @@ SCM_API SCM scm_assv_remove_x (SCM alist, SCM key);
 SCM_API SCM scm_assoc_remove_x (SCM alist, SCM key);
 SCM_INTERNAL void scm_init_alist (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_ALIST_H */
 
 /*
diff --git a/libguile/arbiters.h b/libguile/arbiters.h
index 214e92a..8e9b27c 100644
--- a/libguile/arbiters.h
+++ b/libguile/arbiters.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_make_arbiter (SCM name);
@@ -32,6 +36,10 @@ SCM_API SCM scm_try_arbiter (SCM arb);
 SCM_API SCM scm_release_arbiter (SCM arb);
 SCM_INTERNAL void scm_init_arbiters (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_ARBITERS_H */
 
 /*
diff --git a/libguile/array-handle.h b/libguile/array-handle.h
index a623b4e..c8cdb02 100644
--- a/libguile/array-handle.h
+++ b/libguile/array-handle.h
@@ -28,6 +28,10 @@
 #include "libguile/error.h"
 #include "libguile/numbers.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 typedef SCM (*scm_t_vector_ref) (SCM, size_t);
@@ -131,6 +135,9 @@ scm_array_handle_set (scm_t_array_handle *h, ssize_t p, SCM v)
 
 SCM_INTERNAL void scm_init_array_handle (void);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_ARRAY_HANDLE_H */
 
diff --git a/libguile/array-map.h b/libguile/array-map.h
index b0592d8..0a25df4 100644
--- a/libguile/array-map.h
+++ b/libguile/array-map.h
@@ -26,6 +26,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API int scm_ra_matchp (SCM ra0, SCM ras);
@@ -55,6 +59,10 @@ SCM_DEPRECATED int scm_array_identity (SCM src, SCM dst);
 
 #endif  /* SCM_ENABLE_DEPRECATED == 1 */
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_ARRAY_MAP_H */
 
 /*
diff --git a/libguile/arrays.h b/libguile/arrays.h
index 5f40597..918913e 100644
--- a/libguile/arrays.h
+++ b/libguile/arrays.h
@@ -27,6 +27,10 @@
 #include "libguile/__scm.h"
 #include "libguile/print.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* Multidimensional arrays. Woo hoo!
@@ -72,6 +76,10 @@ SCM_INTERNAL int scm_i_print_array (SCM array, SCM port, scm_print_state *pstate
 
 SCM_INTERNAL void scm_init_arrays (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_ARRAYS_H */
 
 /*
diff --git a/libguile/async.h b/libguile/async.h
index 00b7914..8b52faf 100644
--- a/libguile/async.h
+++ b/libguile/async.h
@@ -28,6 +28,10 @@
 #include "libguile/root.h"
 #include "libguile/threads.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API void scm_async_tick (void);
@@ -104,6 +108,10 @@ SCM_API void scm_critical_section_end (void);
 
 SCM_INTERNAL void scm_init_async (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_ASYNC_H */
 
 /*
diff --git a/libguile/backtrace.h b/libguile/backtrace.h
index 42bd26f..0f081b2 100644
--- a/libguile/backtrace.h
+++ b/libguile/backtrace.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API SCM scm_print_exception (SCM port, SCM frame, SCM key, SCM args);
 
 SCM_API void scm_display_error_message (SCM message, SCM args, SCM port);
@@ -42,6 +46,10 @@ SCM_API SCM scm_set_print_params_x (SCM params);
 
 SCM_INTERNAL void scm_init_backtrace (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_BACKTRACE_H */
 
 /*
diff --git a/libguile/bdw-gc.h b/libguile/bdw-gc.h
index 6e2f456..5e4bbce 100644
--- a/libguile/bdw-gc.h
+++ b/libguile/bdw-gc.h
@@ -46,6 +46,10 @@
 
 #include <gc/gc.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Return true if PTR points to the heap.  */
 #define SCM_I_IS_POINTER_TO_THE_HEAP(ptr)	\
   (GC_base (ptr) != NULL)
@@ -60,5 +64,8 @@
    ? GC_GENERAL_REGISTER_DISAPPEARING_LINK ((link), (obj))	\
    : 0)
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif /* SCM_BDW_GC_H */
diff --git a/libguile/bitvectors.h b/libguile/bitvectors.h
index 6b2cb1e..d3c03b9 100644
--- a/libguile/bitvectors.h
+++ b/libguile/bitvectors.h
@@ -26,6 +26,10 @@
 #include "libguile/__scm.h"
 #include "libguile/array-handle.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* Bitvectors. Exciting stuff, maybe!
@@ -75,6 +79,10 @@ SCM_INTERNAL int scm_i_print_bitvector (SCM vec, SCM port, scm_print_state *psta
 SCM_INTERNAL SCM scm_i_bitvector_equal_p (SCM vec1, SCM vec2);
 SCM_INTERNAL void scm_init_bitvectors (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_BITVECTORS_H */
 
 /*
diff --git a/libguile/boolean.h b/libguile/boolean.h
index df72728..ff3eb41 100644
--- a/libguile/boolean.h
+++ b/libguile/boolean.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* Boolean Values. Obviously there are #t and #f, but there is also nil to deal
@@ -130,6 +134,10 @@ SCM_API SCM scm_nil_p (SCM obj);
 
 SCM_INTERNAL void scm_init_boolean (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_BOOLEAN_H */
 
 /*
diff --git a/libguile/bytevectors.h b/libguile/bytevectors.h
index a5eeaea..e77896f 100644
--- a/libguile/bytevectors.h
+++ b/libguile/bytevectors.h
@@ -23,6 +23,9 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /* R6RS bytevectors.  */
 
@@ -148,4 +151,8 @@ SCM_INTERNAL SCM scm_c_shrink_bytevector (SCM, size_t);
 SCM_INTERNAL void scm_i_bytevector_generalized_set_x (SCM, size_t, SCM);
 SCM_INTERNAL SCM scm_null_bytevector;
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* SCM_BYTEVECTORS_H */
diff --git a/libguile/chars.h b/libguile/chars.h
index 488dd25..b4d6cd9 100644
--- a/libguile/chars.h
+++ b/libguile/chars.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifndef SCM_T_WCHAR_DEFINED
 typedef scm_t_int32 scm_t_wchar;
 #define SCM_T_WCHAR_DEFINED
@@ -90,6 +94,10 @@ SCM_INTERNAL SCM scm_i_charname_to_char (const char *charname,
                                          size_t charname_len);
 SCM_INTERNAL void scm_init_chars (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_CHARS_H */
 
 /*
diff --git a/libguile/continuations.h b/libguile/continuations.h
index ec12b46..37a82d9 100644
--- a/libguile/continuations.h
+++ b/libguile/continuations.h
@@ -29,6 +29,11 @@
 #include <signal.h>
 #include <ucontext.h>
 #endif /* __ia64__ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 #define SCM_CONTINUATIONP(x) \
@@ -96,6 +101,10 @@ scm_i_with_continuation_barrier (scm_t_catch_body body,
 
 SCM_INTERNAL void scm_init_continuations (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_CONTINUATIONS_H */
 
 /*
diff --git a/libguile/control.h b/libguile/control.h
index 4b76591..950d71a 100644
--- a/libguile/control.h
+++ b/libguile/control.h
@@ -21,6 +21,9 @@
 
 #include "libguile/vm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 SCM_INTERNAL SCM scm_i_prompt_pop_abort_args_x (struct scm_vm *vp);
 
@@ -31,5 +34,8 @@ SCM_INTERNAL SCM scm_abort_to_prompt_star (SCM tag, SCM args) SCM_NORETURN;
 
 SCM_INTERNAL void scm_init_control (void);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif /* SCM_CONTROL_H */
diff --git a/libguile/debug-malloc.h b/libguile/debug-malloc.h
index 7830adb..9b1ce1e 100644
--- a/libguile/debug-malloc.h
+++ b/libguile/debug-malloc.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API void scm_malloc_register (void *obj, const char *what);
@@ -36,6 +40,10 @@ SCM_API SCM scm_malloc_stats (void);
 SCM_INTERNAL void scm_debug_malloc_prehistory (void);
 SCM_INTERNAL void scm_init_debug_malloc (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_DEBUG_MALLOC_H */
 
 /*
diff --git a/libguile/debug.h b/libguile/debug.h
index ab301a0..5dec284 100644
--- a/libguile/debug.h
+++ b/libguile/debug.h
@@ -27,6 +27,11 @@
 #include "libguile/__scm.h"
 
 #include "libguile/options.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_local_eval (SCM exp, SCM env);
@@ -40,6 +45,10 @@ SCM_INTERNAL void scm_init_debug (void);
 SCM_API SCM scm_debug_hang (SCM obj);
 #endif /*GUILE_DEBUG*/
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_DEBUG_H */
 
 /*
diff --git a/libguile/deprecated.h b/libguile/deprecated.h
index 1f13bde..6d4b410 100644
--- a/libguile/deprecated.h
+++ b/libguile/deprecated.h
@@ -29,6 +29,10 @@
 #include "libguile/throw.h"
 #include "libguile/iselect.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #if (SCM_ENABLE_DEPRECATED == 1)
 
 /* Deprecated 13-05-2011 because it's better just to scm_dynwind_begin.
@@ -223,4 +227,8 @@ void scm_i_init_deprecated (void);
 
 #endif
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* SCM_DEPRECATED_H */
diff --git a/libguile/deprecation.h b/libguile/deprecation.h
index 06027c6..50b858f 100644
--- a/libguile/deprecation.h
+++ b/libguile/deprecation.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* These functions are a possibly useful part of the API and not only used
@@ -38,6 +42,10 @@ SCM_API SCM scm_issue_deprecation_warning (SCM msgs);
 SCM_API SCM scm_include_deprecated_features (void);
 SCM_INTERNAL void scm_init_deprecation (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_DEPRECATION_H */
 
 /*
diff --git a/libguile/dynl.h b/libguile/dynl.h
index e735bcc..08562cf 100644
--- a/libguile/dynl.h
+++ b/libguile/dynl.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_dynamic_link (SCM fname);
@@ -36,6 +40,10 @@ SCM_API SCM scm_dynamic_call (SCM symb, SCM dobj);
 
 SCM_INTERNAL void scm_init_dynamic_linking (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_DYNL_H */
 
 /*
diff --git a/libguile/dynstack.h b/libguile/dynstack.h
index 7b31ace..8531041 100644
--- a/libguile/dynstack.h
+++ b/libguile/dynstack.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 typedef struct
@@ -201,6 +205,10 @@ SCM_INTERNAL void scm_dynstack_wind_prompt (scm_t_dynstack *, scm_t_bits *,
                                             scm_t_ptrdiff, scm_i_jmp_buf *);
 
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_DYNSTACK_H */
 
 /*
diff --git a/libguile/dynwind.h b/libguile/dynwind.h
index 9ade05c..4f1091d 100644
--- a/libguile/dynwind.h
+++ b/libguile/dynwind.h
@@ -26,6 +26,10 @@
 #include "libguile/__scm.h"
 #include "libguile/dynstack.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_dynamic_wind (SCM thunk1, SCM thunk2, SCM thunk3);
@@ -57,6 +61,9 @@ SCM_API void scm_dynwind_rewind_handler_with_scm (void (*func) (SCM), SCM data,
 
 SCM_API void scm_dynwind_free (void *mem);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_DYNWIND_H */
 
diff --git a/libguile/elf.h b/libguile/elf.h
index 9d53721..f30d5c0 100644
--- a/libguile/elf.h
+++ b/libguile/elf.h
@@ -25,6 +25,10 @@
 
 #include <stdint.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Type for a 16-bit quantity.  */
 typedef uint16_t Elf32_Half;
 typedef uint16_t Elf64_Half;
@@ -2790,5 +2794,8 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_M32R_GOTOFF_LO	64	/* Low 16 bit offset to GOT */
 #define R_M32R_NUM		256	/* Keep this the last entry. */
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif	/* elf.h */
diff --git a/libguile/eq.h b/libguile/eq.h
index c09d667..55f0822 100644
--- a/libguile/eq.h
+++ b/libguile/eq.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* scm_is_eq is defined in tags.h for some reason. */
@@ -39,6 +43,10 @@ SCM_API SCM scm_eqv_p (SCM x, SCM y);
 SCM_API SCM scm_equal_p (SCM x, SCM y);
 SCM_INTERNAL void scm_init_eq (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_EQ_H */
 
 /*
diff --git a/libguile/error.h b/libguile/error.h
index 6985dbc..78326d1 100644
--- a/libguile/error.h
+++ b/libguile/error.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 SCM_API SCM scm_system_error_key;
 SCM_API SCM scm_num_overflow_key;
@@ -70,6 +74,10 @@ SCM_API void scm_misc_error (const char *subr, const char *message,
 			     SCM args) SCM_NORETURN;
 SCM_INTERNAL void scm_init_error (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_ERROR_H */
 
 /*
diff --git a/libguile/evalext.h b/libguile/evalext.h
index 7718ec6..7c2436c 100644
--- a/libguile/evalext.h
+++ b/libguile/evalext.h
@@ -25,12 +25,20 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_defined_p (SCM sym, SCM env);
 SCM_API SCM scm_self_evaluating_p (SCM obj);
 SCM_INTERNAL void scm_init_evalext (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_EVALEXT_H */
 
 /*
diff --git a/libguile/expand.h b/libguile/expand.h
index 9c2732d..e7b72d9 100644
--- a/libguile/expand.h
+++ b/libguile/expand.h
@@ -26,6 +26,9 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 \f
 
@@ -341,6 +344,9 @@ SCM_INTERNAL SCM scm_convert_assignment (SCM exp);
 
 SCM_INTERNAL void scm_init_expand (void);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_EXPAND_H */
 
diff --git a/libguile/extensions.h b/libguile/extensions.h
index 765f9be..3590647 100644
--- a/libguile/extensions.h
+++ b/libguile/extensions.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 typedef void (*scm_t_extension_init_func)(void*);
@@ -37,6 +41,10 @@ SCM_API SCM scm_load_extension (SCM lib, SCM init);
 
 SCM_INTERNAL void scm_init_extensions (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_EXTENSIONS_H */
 
 /*
diff --git a/libguile/feature.h b/libguile/feature.h
index 467f9ed..28e41cd 100644
--- a/libguile/feature.h
+++ b/libguile/feature.h
@@ -26,6 +26,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API void scm_add_feature (const char* str);
 SCM_API SCM scm_program_arguments (void);
 SCM_API void scm_set_program_arguments (int argc, char **argv, char *first);
@@ -34,6 +38,10 @@ SCM_API SCM scm_set_program_arguments_scm (SCM lst);
 SCM_INTERNAL SCM scm_program_arguments_fluid;
 SCM_INTERNAL void scm_init_feature (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_FEATURE_H */
 
 /*
diff --git a/libguile/filesys.h b/libguile/filesys.h
index fc66e40..b7b8e8d 100644
--- a/libguile/filesys.h
+++ b/libguile/filesys.h
@@ -26,6 +26,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API scm_t_bits scm_tc16_dir;
@@ -72,6 +76,10 @@ SCM_INTERNAL SCM scm_i_relativize_path (SCM path, SCM in_path);
 
 SCM_INTERNAL void scm_init_filesys (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_FILESYS_H */
 
 /*
diff --git a/libguile/finalizers.h b/libguile/finalizers.h
index d01d1b7..7707fd5 100644
--- a/libguile/finalizers.h
+++ b/libguile/finalizers.h
@@ -23,6 +23,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 typedef void (*scm_t_finalizer_proc) (void *obj, void *data);
@@ -47,4 +51,8 @@ SCM_API int scm_run_finalizers (void);
 SCM_INTERNAL void scm_init_finalizers (void);
 SCM_INTERNAL void scm_init_finalizer_thread (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_FINALIZERS_H */
diff --git a/libguile/fluids.h b/libguile/fluids.h
index a550d9a..ba0d1fb 100644
--- a/libguile/fluids.h
+++ b/libguile/fluids.h
@@ -27,6 +27,9 @@
 #include "libguile/root.h"
 #include "libguile/vectors.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /* Fluids.
 
@@ -91,6 +94,10 @@ SCM_INTERNAL void scm_i_fluid_print (SCM exp, SCM port, scm_print_state *pstate)
 SCM_INTERNAL void scm_i_dynamic_state_print (SCM exp, SCM port, scm_print_state *pstate);
 SCM_INTERNAL void scm_init_fluids (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_FLUIDS_H */
 
 /*
diff --git a/libguile/foreign-object.h b/libguile/foreign-object.h
index 806b7ed..3f5e84e 100644
--- a/libguile/foreign-object.h
+++ b/libguile/foreign-object.h
@@ -24,6 +24,9 @@
 #include "libguile/__scm.h"
 #include "libguile/print.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 \f
 
@@ -58,5 +61,8 @@ SCM_API void scm_foreign_object_signed_set_x (SCM obj, size_t n,
 
 SCM_INTERNAL void scm_register_foreign_object (void);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_FOREIGN_OBJECT_H */
diff --git a/libguile/foreign.h b/libguile/foreign.h
index fbb9764..6546860 100644
--- a/libguile/foreign.h
+++ b/libguile/foreign.h
@@ -21,6 +21,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* A "foreign pointer" is a wrapped C pointer.  It is represented by a
    cell whose second word is a pointer.  The first word has the
    `scm_tc7_pointer' type code.
@@ -106,4 +110,8 @@ SCM_INTERNAL int scm_i_foreign_arity (SCM foreign,
 SCM_INTERNAL void scm_register_foreign (void);
 
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* SCM_FOREIGN_H */
diff --git a/libguile/fports.h b/libguile/fports.h
index 092b43e..d01bdb9 100644
--- a/libguile/fports.h
+++ b/libguile/fports.h
@@ -27,6 +27,10 @@
 
 #include "libguile/ports.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* struct allocated for each buffered FPORT.  */
@@ -75,6 +79,9 @@ SCM_INTERNAL void scm_init_fports (void);
 
 SCM_INTERNAL SCM scm_i_fdes_to_port (int fdes, long mode_bits, SCM name);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_FPORTS_H */
 
diff --git a/libguile/frames.h b/libguile/frames.h
index 31f8634..bb0fa2f 100644
--- a/libguile/frames.h
+++ b/libguile/frames.h
@@ -22,6 +22,10 @@
 #include <libguile.h>
 #include "programs.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 /* Stack frames
    ------------
@@ -177,6 +181,10 @@ SCM_INTERNAL void scm_i_frame_print (SCM frame, SCM port,
                                      scm_print_state *pstate);
 SCM_INTERNAL void scm_init_frames (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _SCM_FRAMES_H_ */
 
 /*
diff --git a/libguile/gc-inline.h b/libguile/gc-inline.h
index fcbe5a5..c32089b 100644
--- a/libguile/gc-inline.h
+++ b/libguile/gc-inline.h
@@ -47,7 +47,17 @@
 #include "libguile/bdw-gc.h"
 #include "libguile/threads.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 #include <gc/gc_inline.h> /* GC_generic_malloc_many */
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 \f
 
@@ -173,6 +183,9 @@ scm_inline_cons (scm_i_thread *thread, SCM x, SCM y)
   return scm_inline_cell (thread, SCM_UNPACK (x), SCM_UNPACK (y));
 }
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_GC_INLINE_H */
 
diff --git a/libguile/gc.h b/libguile/gc.h
index 8b3ae79..1190c46 100644
--- a/libguile/gc.h
+++ b/libguile/gc.h
@@ -29,6 +29,10 @@
 #include "libguile/hooks.h"
 #include "libguile/threads.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 typedef struct scm_t_cell
 {
@@ -331,6 +335,10 @@ SCM_INTERNAL void scm_storage_prehistory (void);
 SCM_INTERNAL void scm_init_gc_protect_object (void);
 SCM_INTERNAL void scm_init_gc (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_GC_H */
 
 /*
diff --git a/libguile/generalized-arrays.h b/libguile/generalized-arrays.h
index dfdb8bd..59908ef 100644
--- a/libguile/generalized-arrays.h
+++ b/libguile/generalized-arrays.h
@@ -26,6 +26,10 @@
 #include "libguile/__scm.h"
 #include "libguile/array-handle.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* These functions operate on all kinds of arrays that Guile knows about.
@@ -64,6 +68,9 @@ SCM_API SCM scm_array_to_list (SCM v);
 
 SCM_INTERNAL void scm_init_generalized_arrays (void);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_GENERALIZED_ARRAYS_H */
 
diff --git a/libguile/generalized-vectors.h b/libguile/generalized-vectors.h
index 876537a..46881bd 100644
--- a/libguile/generalized-vectors.h
+++ b/libguile/generalized-vectors.h
@@ -26,6 +26,10 @@
 #include "libguile/__scm.h"
 #include "libguile/array-handle.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* Generalized vectors */
@@ -46,6 +50,10 @@ SCM_INTERNAL void scm_i_register_vector_constructor (SCM type, SCM (*ctor)(SCM,
 
 SCM_INTERNAL void scm_init_generalized_vectors (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_GENERALIZED_VECTORS_H */
 
 /*
diff --git a/libguile/gettext.h b/libguile/gettext.h
index d4576bd..e0b7da2 100644
--- a/libguile/gettext.h
+++ b/libguile/gettext.h
@@ -23,6 +23,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
 SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
 SCM_API SCM scm_textdomain (SCM domainname);
@@ -33,6 +37,10 @@ SCM_INTERNAL int scm_i_to_lc_category (SCM category, int allow_lc_all);
 
 SCM_INTERNAL void scm_init_gettext (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_GETTEXT_H */
 
 /*
diff --git a/libguile/goops.h b/libguile/goops.h
index cc743a6..fcd27e1 100644
--- a/libguile/goops.h
+++ b/libguile/goops.h
@@ -34,6 +34,10 @@
 
 #include "libguile/validate.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* {Class flags}
  *
  * These are used for efficient identification of instances of a
@@ -142,6 +146,10 @@ SCM_INTERNAL SCM scm_i_define_class_for_vtable (SCM vtable);
 
 SCM_INTERNAL void scm_init_goops (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_GOOPS_H */
 
 /*
diff --git a/libguile/gsubr.h b/libguile/gsubr.h
index 065b947..1213e2b 100644
--- a/libguile/gsubr.h
+++ b/libguile/gsubr.h
@@ -26,6 +26,9 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 \f
 
@@ -70,6 +73,10 @@ SCM_API SCM scm_c_define_gsubr_with_generic (const char *name,
 
 SCM_INTERNAL void scm_init_gsubr (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_GSUBR_H */
 
 /*
diff --git a/libguile/guardians.h b/libguile/guardians.h
index a23026d..398032a 100644
--- a/libguile/guardians.h
+++ b/libguile/guardians.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API SCM scm_make_guardian (void);
 
 SCM_INTERNAL void scm_i_init_guardians_for_gc (void);
@@ -33,6 +37,10 @@ SCM_INTERNAL int scm_i_mark_inaccessible_guardeds (void);
 
 SCM_INTERNAL void scm_init_guardians (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_GUARDIANS_H */
 
 /*
diff --git a/libguile/hash.h b/libguile/hash.h
index 9085bc0..d9eee3c 100644
--- a/libguile/hash.h
+++ b/libguile/hash.h
@@ -26,6 +26,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_INTERNAL unsigned long scm_i_locale_string_hash (const char *str,
@@ -44,6 +48,10 @@ SCM_API unsigned long scm_ihash (SCM obj, unsigned long n);
 SCM_API SCM scm_hash (SCM obj, SCM n);
 SCM_INTERNAL void scm_init_hash (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_HASH_H */
 
 /*
diff --git a/libguile/hashtab.h b/libguile/hashtab.h
index 82ed22e..6ac2fd1 100644
--- a/libguile/hashtab.h
+++ b/libguile/hashtab.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 #define SCM_HASHTABLE_P(x) (SCM_HAS_TYP7 (x, scm_tc7_hashtable))
@@ -138,6 +142,10 @@ SCM_API SCM scm_hash_count (SCM hash, SCM pred);
 SCM_INTERNAL void scm_i_hashtable_print (SCM exp, SCM port, scm_print_state *pstate);
 SCM_INTERNAL void scm_init_hashtab (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_HASHTAB_H */
 
 /*
diff --git a/libguile/hooks.h b/libguile/hooks.h
index dc930cb..2c4072e 100644
--- a/libguile/hooks.h
+++ b/libguile/hooks.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * C level hooks
  */
@@ -91,6 +95,10 @@ SCM_API void scm_c_run_hookn (SCM hook, SCM *argv, size_t nargs);
 SCM_API SCM scm_hook_to_list (SCM hook);
 SCM_INTERNAL void scm_init_hooks (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_HOOKS_H */
 
 /*
diff --git a/libguile/i18n.h b/libguile/i18n.h
index c2792ac..3dda139 100644
--- a/libguile/i18n.h
+++ b/libguile/i18n.h
@@ -23,6 +23,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API SCM scm_global_locale;
 SCM_API SCM scm_make_locale (SCM category_mask, SCM locale_name, SCM base_locale);
 SCM_API SCM scm_locale_p (SCM obj);
@@ -50,6 +54,9 @@ SCM_INTERNAL SCM scm_nl_langinfo (SCM item, SCM locale);
 SCM_INTERNAL void scm_init_i18n (void);
 SCM_INTERNAL void scm_bootstrap_i18n (void);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_I18N_H */
 
diff --git a/libguile/init.h b/libguile/init.h
index bc6cddf..385ffc3 100644
--- a/libguile/init.h
+++ b/libguile/init.h
@@ -26,6 +26,11 @@
 #include "libguile/__scm.h"
 #include "libguile/threads.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
 \f
 SCM_INTERNAL scm_i_pthread_mutex_t scm_i_init_mutex;
 SCM_API int scm_initialized_p;
@@ -42,6 +47,10 @@ SCM_INTERNAL void scm_i_init_guile (void *base);
 
 SCM_API void scm_load_startup_files (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_INIT_H */
 
 /*
diff --git a/libguile/inline.h b/libguile/inline.h
index 3c9b09b..704bc9d 100644
--- a/libguile/inline.h
+++ b/libguile/inline.h
@@ -36,6 +36,10 @@
 #include "libguile/numbers.h"
 #include "libguile/error.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 
 SCM_INLINE int scm_is_string (SCM x);
 
@@ -54,4 +58,9 @@ scm_is_string (SCM x)
 }
 
 #endif
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/libguile/instructions.h b/libguile/instructions.h
index ad058cd..4db02af 100644
--- a/libguile/instructions.h
+++ b/libguile/instructions.h
@@ -22,6 +22,10 @@
 #include <libguile.h>
 #include <libguile/vm-operations.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifdef BUILDING_LIBGUILE
 
 enum scm_opcode
@@ -48,6 +52,10 @@ SCM_INTERNAL SCM scm_instruction_list (void);
 SCM_INTERNAL void scm_bootstrap_instructions (void);
 SCM_INTERNAL void scm_init_instructions (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _SCM_INSTRUCTIONS_H_ */
 
 /*
diff --git a/libguile/ioext.h b/libguile/ioext.h
index 1b7b93a..48bfa7c 100644
--- a/libguile/ioext.h
+++ b/libguile/ioext.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_ftell (SCM object);
@@ -38,6 +42,10 @@ SCM_API SCM scm_primitive_move_to_fdes (SCM port, SCM fd);
 SCM_API SCM scm_fdes_to_ports (SCM fd);
 SCM_INTERNAL void scm_init_ioext (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_IOEXT_H */
 
 /*
diff --git a/libguile/iselect.h b/libguile/iselect.h
index 945ad14..84fac21 100644
--- a/libguile/iselect.h
+++ b/libguile/iselect.h
@@ -31,6 +31,10 @@
 
 #include <sys/select.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API int scm_std_select (int fds,
 			    fd_set *rfds,
 			    fd_set *wfds,
@@ -39,6 +43,10 @@ SCM_API int scm_std_select (int fds,
 
 #define SELECT_TYPE fd_set
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_ISELECT_H */
 
 /*
diff --git a/libguile/keywords.h b/libguile/keywords.h
index 32311dd..bf45850 100644
--- a/libguile/keywords.h
+++ b/libguile/keywords.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_keyword_p (SCM obj);
@@ -51,6 +55,10 @@ scm_c_bind_keyword_arguments (const char *subr, SCM rest,
 
 SCM_INTERNAL void scm_init_keywords (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_KEYWORDS_H */
 
 /*
diff --git a/libguile/libgettext.h b/libguile/libgettext.h
index f54b6bf..30004ea 100644
--- a/libguile/libgettext.h
+++ b/libguile/libgettext.h
@@ -37,6 +37,10 @@
 # include <locale.h>
 #endif
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Disabled NLS.
    The casts to 'const char *' serve the purpose of producing warnings
    for invalid uses of the value returned from these functions.
@@ -55,6 +59,14 @@
 # define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
 # define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
 
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
 #endif
 
 /* A pseudo function call that serves as a marker for the automated
@@ -66,4 +78,8 @@
    initializer for static 'char[]' or 'const char[]' variables.  */
 #define gettext_noop(String) String
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _LIBGETTEXT_H */
diff --git a/libguile/list.h b/libguile/list.h
index 238926e..3b8b1c3 100644
--- a/libguile/list.h
+++ b/libguile/list.h
@@ -26,6 +26,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_list_1 (SCM e1);
@@ -76,6 +80,10 @@ SCM_API SCM scm_copy_tree (SCM obj);
 SCM_INTERNAL SCM scm_i_finite_list_copy (SCM /* a list known to be finite */);
 SCM_INTERNAL void scm_init_list (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_LIST_H */
 
 /*
diff --git a/libguile/load.h b/libguile/load.h
index 986948d..7414118 100644
--- a/libguile/load.h
+++ b/libguile/load.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 SCM_API SCM scm_parse_path (SCM path, SCM tail);
 SCM_API SCM scm_parse_path_with_ellipsis (SCM path, SCM base);
@@ -46,6 +50,10 @@ SCM_INTERNAL void scm_init_load_should_auto_compile (void);
 SCM_INTERNAL void scm_init_eval_in_scheme (void);
 SCM_INTERNAL char *scm_i_mirror_backslashes (char *path);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_LOAD_H */
 
 /*
diff --git a/libguile/loader.h b/libguile/loader.h
index 6fd9502..ff3060e 100644
--- a/libguile/loader.h
+++ b/libguile/loader.h
@@ -21,6 +21,10 @@
 
 #include <libguile.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API SCM scm_load_thunk_from_file (SCM filename);
 SCM_API SCM scm_load_thunk_from_memory (SCM bv);
 
@@ -30,6 +34,10 @@ scm_find_dead_slot_map_unlocked (const scm_t_uint32 *ip);
 SCM_INTERNAL void scm_bootstrap_loader (void);
 SCM_INTERNAL void scm_init_loader (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _SCM_LOADER_H_ */
 
 /*
diff --git a/libguile/macros.h b/libguile/macros.h
index de2496e..bdd3a0d 100644
--- a/libguile/macros.h
+++ b/libguile/macros.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 typedef SCM (*scm_t_macro_primitive) (SCM, SCM);
@@ -43,6 +47,9 @@ SCM_INTERNAL scm_t_macro_primitive scm_i_macro_primitive (SCM m);
 
 SCM_INTERNAL void scm_init_macros (void);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_MACROS_H */
 
diff --git a/libguile/mallocs.h b/libguile/mallocs.h
index 9c797e9..de052b7 100644
--- a/libguile/mallocs.h
+++ b/libguile/mallocs.h
@@ -25,6 +25,11 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
 \f
 SCM_API scm_t_bits scm_tc16_malloc;
 
@@ -37,6 +42,10 @@ SCM_API scm_t_bits scm_tc16_malloc;
 SCM_API SCM scm_malloc_obj (size_t n);
 SCM_INTERNAL void scm_init_mallocs (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_MALLOCS_H */
 
 /*
diff --git a/libguile/memoize.h b/libguile/memoize.h
index 23c0306..e920260 100644
--- a/libguile/memoize.h
+++ b/libguile/memoize.h
@@ -26,6 +26,9 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 \f
 
@@ -93,6 +96,10 @@ SCM_INTERNAL SCM scm_sys_resolve_variable (SCM loc, SCM module);
 SCM_INTERNAL void scm_init_memoize (void);
 
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_MEMOIZE_H */
 
 /*
diff --git a/libguile/modules.h b/libguile/modules.h
index 28df6c6..d5d8552 100644
--- a/libguile/modules.h
+++ b/libguile/modules.h
@@ -27,6 +27,10 @@
 
 #include "libguile/validate.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API int scm_module_system_booted_p;
@@ -122,6 +126,10 @@ SCM_API SCM scm_get_pre_modules_obarray (void);
 SCM_INTERNAL void scm_modules_prehistory (void);
 SCM_INTERNAL void scm_init_modules (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_MODULES_H */
 
 /*
diff --git a/libguile/net_db.h b/libguile/net_db.h
index 68b2a8b..c485414 100644
--- a/libguile/net_db.h
+++ b/libguile/net_db.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_gethost (SCM host);
@@ -39,6 +43,10 @@ SCM_API SCM scm_getaddrinfo (SCM, SCM, SCM, SCM, SCM, SCM);
 SCM_API SCM scm_gai_strerror (SCM);
 SCM_INTERNAL void scm_init_net_db (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_NET_DB_H */
 
 /*
diff --git a/libguile/null-threads.h b/libguile/null-threads.h
index 116b845..b26a937 100644
--- a/libguile/null-threads.h
+++ b/libguile/null-threads.h
@@ -36,6 +36,10 @@
 #include <stdlib.h>
 #include <errno.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Threads
 */
 #define scm_i_pthread_t                     int
@@ -102,6 +106,9 @@ SCM_API int scm_i_pthread_key_create (scm_i_pthread_key_t *key,
 #define scm_i_scm_pthread_cond_wait         scm_i_pthread_cond_wait
 #define scm_i_scm_pthread_cond_timedwait    scm_i_pthread_cond_timedwait
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_NULL_THREADS_H */
 
diff --git a/libguile/numbers.h b/libguile/numbers.h
index bba336b..6226bb9 100644
--- a/libguile/numbers.h
+++ b/libguile/numbers.h
@@ -29,6 +29,10 @@
 #include "libguile/__scm.h"
 #include "libguile/print.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifndef SCM_T_WCHAR_DEFINED
 typedef scm_t_int32 scm_t_wchar;
 #define SCM_T_WCHAR_DEFINED
@@ -101,6 +105,10 @@ typedef scm_t_int32 scm_t_wchar;
  * SCM_FLTMAX is less than or scm_equal the largest single precision float
  */
 
+#ifdef __cplusplus
+}
+#endif
+
 #if SCM_HAVE_STDC_HEADERS
 # ifndef GO32
 #  include <float.h>
@@ -111,6 +119,10 @@ typedef scm_t_int32 scm_t_wchar;
 # endif /* ndef GO32 */
 #endif /* def STDC_HEADERS */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifdef DBL_MAX_10_EXP
 # define SCM_MAXEXP DBL_MAX_10_EXP
 #else
@@ -592,6 +604,10 @@ SCM_API int scm_install_gmp_memory_functions;
 
 SCM_INTERNAL void scm_init_numbers (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_NUMBERS_H */
 
 /*
diff --git a/libguile/objprop.h b/libguile/objprop.h
index f9a2e94..11e6545 100644
--- a/libguile/objprop.h
+++ b/libguile/objprop.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_object_properties (SCM obj);
@@ -33,6 +37,10 @@ SCM_API SCM scm_object_property (SCM obj, SCM key);
 SCM_API SCM scm_set_object_property_x (SCM obj, SCM key, SCM val);
 SCM_INTERNAL void scm_init_objprop (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_OBJPROP_H */
 
 /*
diff --git a/libguile/options.h b/libguile/options.h
index 8ea960b..8e1bae2 100644
--- a/libguile/options.h
+++ b/libguile/options.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 typedef struct scm_t_option
@@ -46,6 +50,10 @@ SCM_API SCM scm_options (SCM, scm_t_option [], const char*);
 SCM_API void scm_init_opts (SCM (*) (SCM), scm_t_option []);
 SCM_INTERNAL void scm_init_options (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_OPTIONS_H */
 
 /*
diff --git a/libguile/pairs.h b/libguile/pairs.h
index 130bf28..f12b2f1 100644
--- a/libguile/pairs.h
+++ b/libguile/pairs.h
@@ -27,6 +27,10 @@
 
 #include "libguile/gc.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 #if (SCM_DEBUG_PAIR_ACCESSES == 1)
@@ -212,6 +216,11 @@ SCM_API SCM scm_caaaar (SCM x);
 
 SCM_INTERNAL void scm_init_pairs (void);
 
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_PAIRS_H */
 
 /*
diff --git a/libguile/poll.h b/libguile/poll.h
index ab31950..088aceb 100644
--- a/libguile/poll.h
+++ b/libguile/poll.h
@@ -25,10 +25,18 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_INTERNAL void scm_register_poll (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_POLL_H */
 
 /*
diff --git a/libguile/ports-internal.h b/libguile/ports-internal.h
index bff89cb..5bebb6b 100644
--- a/libguile/ports-internal.h
+++ b/libguile/ports-internal.h
@@ -25,6 +25,10 @@
 #include "libguile/_scm.h"
 #include "libguile/ports.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 enum scm_port_encoding_mode {
   SCM_PORT_ENCODING_MODE_UTF8,
   SCM_PORT_ENCODING_MODE_LATIN1,
@@ -63,4 +67,8 @@ typedef struct scm_port_internal scm_t_port_internal;
 SCM_INTERNAL scm_t_iconv_descriptors *
 scm_i_port_iconv_descriptors (SCM port, scm_t_port_rw_active mode);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/libguile/ports.h b/libguile/ports.h
index f2ab850..ceb730e 100644
--- a/libguile/ports.h
+++ b/libguile/ports.h
@@ -37,6 +37,10 @@
 #include "libguile/threads.h"
 #include "libguile/strings.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 #define SCM_INITIAL_PUTBACK_BUF_SIZE 4
@@ -461,6 +465,10 @@ scm_puts_unlocked (const char *s, SCM port)
 }
 #endif  /* SCM_CAN_INLINE || defined SCM_INLINE_C_IMPLEMENTING_INLINES */
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_PORTS_H */
 
 /*
diff --git a/libguile/posix.h b/libguile/posix.h
index 92f8b35..e729708 100644
--- a/libguile/posix.h
+++ b/libguile/posix.h
@@ -27,6 +27,9 @@
 #include "libguile/__scm.h"
 #include "libguile/threads.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 \f
 
@@ -96,6 +99,10 @@ SCM_INTERNAL void scm_init_posix (void);
 
 SCM_INTERNAL scm_i_pthread_mutex_t scm_i_locale_mutex;
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_POSIX_H */
 
 /*
diff --git a/libguile/print.h b/libguile/print.h
index 80a9922..a8608d9 100644
--- a/libguile/print.h
+++ b/libguile/print.h
@@ -28,6 +28,11 @@
 
 #include "libguile/chars.h" 
 #include "libguile/options.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* State information passed around during printing.
@@ -103,6 +108,10 @@ SCM_INTERNAL void scm_init_print (void);
 SCM_API SCM scm_current_pstate (void);
 #endif 
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_PRINT_H */
 
 /*
diff --git a/libguile/private-options.h b/libguile/private-options.h
index a3a0c2b..af1fa6c 100644
--- a/libguile/private-options.h
+++ b/libguile/private-options.h
@@ -25,6 +25,10 @@
 #ifndef PRIVATE_OPTIONS
 #define PRIVATE_OPTIONS
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
   debugging.
  */
@@ -73,4 +77,8 @@ SCM_INTERNAL scm_t_option scm_read_opts[];
 
 #define SCM_N_READ_OPTIONS 9
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* PRIVATE_OPTIONS */ 
diff --git a/libguile/procprop.h b/libguile/procprop.h
index 41d0753..218d10e 100644
--- a/libguile/procprop.h
+++ b/libguile/procprop.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_sym_name;
@@ -46,6 +50,10 @@ SCM_API SCM scm_procedure_name (SCM proc);
 SCM_API SCM scm_procedure_documentation (SCM proc);
 SCM_INTERNAL void scm_init_procprop (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_PROCPROP_H */
 
 /*
diff --git a/libguile/procs.h b/libguile/procs.h
index c4c78f2..64a42e0 100644
--- a/libguile/procs.h
+++ b/libguile/procs.h
@@ -26,6 +26,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_procedure_p (SCM obj);
@@ -36,6 +40,10 @@ SCM_API SCM scm_procedure (SCM proc);
 SCM_API SCM scm_setter (SCM proc);
 SCM_INTERNAL void scm_init_procs (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_PROCS_H */
 
 /*
diff --git a/libguile/programs.h b/libguile/programs.h
index d170c1b..09b102e 100644
--- a/libguile/programs.h
+++ b/libguile/programs.h
@@ -21,6 +21,10 @@
 
 #include <libguile.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * Programs
  */
@@ -79,6 +83,10 @@ SCM_INTERNAL void scm_i_program_print (SCM program, SCM port,
 SCM_INTERNAL void scm_bootstrap_programs (void);
 SCM_INTERNAL void scm_init_programs (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _SCM_PROGRAMS_H_ */
 
 /*
diff --git a/libguile/promises.h b/libguile/promises.h
index 66349b5..823f638 100644
--- a/libguile/promises.h
+++ b/libguile/promises.h
@@ -26,6 +26,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* {Promises}
@@ -51,6 +55,9 @@ SCM_API SCM scm_promise_p (SCM x);
 
 SCM_INTERNAL void scm_init_promises (void);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_PROMISES_H */
 
diff --git a/libguile/pthread-threads.h b/libguile/pthread-threads.h
index b5fae4e..0b41f9d 100644
--- a/libguile/pthread-threads.h
+++ b/libguile/pthread-threads.h
@@ -29,6 +29,10 @@
 #include <pthread.h>
 #include <sched.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Threads 
 */
 #define scm_i_pthread_t                     pthread_t
@@ -97,6 +101,10 @@ extern pthread_mutexattr_t scm_i_pthread_mutexattr_recursive[1];
 #define scm_i_scm_pthread_cond_wait         scm_pthread_cond_wait
 #define scm_i_scm_pthread_cond_timedwait    scm_pthread_cond_timedwait
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_PTHREADS_THREADS_H */
 
 /*
diff --git a/libguile/r6rs-ports.h b/libguile/r6rs-ports.h
index 3dde4d5..2667f30 100644
--- a/libguile/r6rs-ports.h
+++ b/libguile/r6rs-ports.h
@@ -23,6 +23,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* R6RS I/O Ports.  */
 
 SCM_API SCM scm_eof_object (void);
@@ -44,4 +48,8 @@ SCM_API SCM scm_get_string_n_x (SCM, SCM, SCM, SCM);
 SCM_API void scm_init_r6rs_ports (void);
 SCM_INTERNAL void scm_register_r6rs_ports (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* SCM_R6RS_PORTS_H */
diff --git a/libguile/random.h b/libguile/random.h
index 109969e..f70b72e 100644
--- a/libguile/random.h
+++ b/libguile/random.h
@@ -25,6 +25,11 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
 \f
 /*
  * A plugin interface for RNGs
@@ -97,6 +102,10 @@ SCM_INTERNAL void scm_init_random (void);
 
 SCM_INTERNAL void scm_i_random_bytes_from_platform (unsigned char *buf, size_t len);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_RANDOM_H */
 
 /*
diff --git a/libguile/rdelim.h b/libguile/rdelim.h
index 2e401e4..fd221ca 100644
--- a/libguile/rdelim.h
+++ b/libguile/rdelim.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API SCM scm_read_delimited_x (SCM delims, SCM buf, SCM gobble, SCM port,
 				  SCM offset, SCM length);
 SCM_API SCM scm_read_line (SCM port);
@@ -33,6 +37,10 @@ SCM_API SCM scm_init_rdelim_builtins (void);
 
 SCM_INTERNAL void scm_init_rdelim (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_RDELIM_H */
 
 /*
diff --git a/libguile/read.h b/libguile/read.h
index 3c47afd..fb3d1c9 100644
--- a/libguile/read.h
+++ b/libguile/read.h
@@ -26,6 +26,11 @@
 #include "libguile/__scm.h"
 
 #include "libguile/options.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* SCM_LINE_INCREMENTORS are the characters which cause the line count to
@@ -64,6 +69,10 @@ SCM_INTERNAL void scm_i_input_error (const char *func, SCM port,
 
 SCM_INTERNAL void scm_init_read (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_READ_H */
 
 /*
diff --git a/libguile/regex-posix.h b/libguile/regex-posix.h
index 8060fe3..a669194 100644
--- a/libguile/regex-posix.h
+++ b/libguile/regex-posix.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API scm_t_bits scm_tc16_regex;
 #define SCM_RGX(X)	((regex_t *) SCM_SMOB_DATA (X))
 #define SCM_RGXP(X)	(SCM_SMOB_PREDICATE (scm_tc16_regex, (X)))
@@ -34,6 +38,10 @@ SCM_API SCM scm_regexp_p (SCM x);
 SCM_API SCM scm_regexp_exec (SCM rx, SCM str, SCM start, SCM flags);
 SCM_INTERNAL void scm_init_regex_posix (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_REGEX_POSIX_H */
 
 /*
diff --git a/libguile/root.h b/libguile/root.h
index 68ab5c7..482f3bc 100644
--- a/libguile/root.h
+++ b/libguile/root.h
@@ -27,6 +27,10 @@
 #include "libguile/debug.h"
 #include "libguile/throw.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_internal_cwdr (scm_t_catch_body body,
@@ -39,6 +43,10 @@ SCM_API SCM scm_dynamic_root (void);
 SCM_API SCM scm_apply_with_dynamic_root (SCM proc, SCM a1, SCM args, SCM handler);
 SCM_INTERNAL void scm_init_root (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_ROOT_H */
 
 /*
diff --git a/libguile/rw.h b/libguile/rw.h
index d54f1b3..6aba35b 100644
--- a/libguile/rw.h
+++ b/libguile/rw.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API SCM scm_read_string_x_partial (SCM str, SCM port_or_fdes, SCM start,
 				       SCM end);
 SCM_API SCM scm_write_string_partial (SCM str, SCM port_or_fdes, SCM start,
@@ -33,6 +37,10 @@ SCM_API SCM scm_write_string_partial (SCM str, SCM port_or_fdes, SCM start,
 SCM_INTERNAL SCM scm_init_rw_builtins (void);
 SCM_INTERNAL void scm_init_rw (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_RW_H */
 
 /*
diff --git a/libguile/scmsigs.h b/libguile/scmsigs.h
index fce3728..890e7eb 100644
--- a/libguile/scmsigs.h
+++ b/libguile/scmsigs.h
@@ -26,6 +26,10 @@
 #include "libguile/__scm.h"
 #include "libguile/threads.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_sigaction (SCM signum, SCM handler, SCM flags);
@@ -48,6 +52,10 @@ SCM_INTERNAL void scm_i_ensure_signal_delivery_thread (void);
 
 SCM_INTERNAL scm_i_thread *scm_i_signal_delivery_thread;
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_SCMSIGS_H */
 
 /*
diff --git a/libguile/script.h b/libguile/script.h
index cf0162a..4ae6ddb 100644
--- a/libguile/script.h
+++ b/libguile/script.h
@@ -25,6 +25,11 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
 \f
 SCM_API char *scm_find_executable (const char *name);
 SCM_API char *scm_find_impl_file (char *exec_path,
@@ -40,6 +45,10 @@ SCM_API char *scm_usage_name;
 SCM_INTERNAL void scm_i_set_boot_program_arguments (int argc, char *argv[]);
 SCM_INTERNAL void scm_init_script (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_SCRIPT_H */
 
 /*
diff --git a/libguile/simpos.h b/libguile/simpos.h
index 1e20768..0bfb0cc 100644
--- a/libguile/simpos.h
+++ b/libguile/simpos.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_system (SCM cmd);
@@ -35,6 +39,10 @@ SCM_API SCM scm_primitive__exit (SCM status);
 SCM_INTERNAL int scm_getenv_int (const char *var, int def);
 SCM_INTERNAL void scm_init_simpos (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_SIMPOS_H */
 
 /*
diff --git a/libguile/smob.h b/libguile/smob.h
index 561a6d1..16ff9c6 100644
--- a/libguile/smob.h
+++ b/libguile/smob.h
@@ -27,6 +27,9 @@
 #include "libguile/__scm.h"
 #include "libguile/print.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 \f
 /* This is the internal representation of a smob type */
@@ -200,6 +203,10 @@ SCM_API SCM scm_make_smob (scm_t_bits tc);
 
 SCM_API void scm_smob_prehistory (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_SMOB_H */
 
 /*
diff --git a/libguile/snarf.h b/libguile/snarf.h
index d0b6833..8f4d398 100644
--- a/libguile/snarf.h
+++ b/libguile/snarf.h
@@ -24,6 +24,10 @@
 
 \f
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Macros for snarfing initialization actions from C source. */
 
 /* Casting to a function that can take any number of arguments.  */
@@ -335,6 +339,10 @@ SCM_SNARF_INIT(scm_set_smob_apply((tag), (c_name), (req), (opt), (rest));)
 #define SCM_ASSERT(_cond, _arg, _pos, _subr) ^^ argpos _arg _pos __LINE__ ^^
 #endif /* SCM_MAGIC_SNARF_DOCS */
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_SNARF_H */
 
 /*
diff --git a/libguile/socket.h b/libguile/socket.h
index a211867..415954d 100644
--- a/libguile/socket.h
+++ b/libguile/socket.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_inet_aton (SCM address);
@@ -61,6 +65,10 @@ SCM_API struct sockaddr *scm_c_make_socket_address (SCM family, SCM address,
 						    size_t *address_size);
 SCM_API SCM scm_make_socket_address (SCM family, SCM address, SCM args);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_SOCKET_H */
 
 /*
diff --git a/libguile/sort.h b/libguile/sort.h
index 3ae86c2..0263ce6 100644
--- a/libguile/sort.h
+++ b/libguile/sort.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_restricted_vector_sort_x (SCM vec,
@@ -42,6 +46,10 @@ SCM_API SCM scm_sort_list (SCM ls, SCM less);
 SCM_API SCM scm_sort_list_x (SCM ls, SCM less);
 SCM_INTERNAL void scm_init_sort (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_SORT_H */
 
 /*
diff --git a/libguile/srcprop.h b/libguile/srcprop.h
index 0252e54..b748c6f 100644
--- a/libguile/srcprop.h
+++ b/libguile/srcprop.h
@@ -26,6 +26,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* {Source properties}
@@ -54,6 +58,9 @@ SCM_INTERNAL void scm_i_set_source_properties_x (SCM obj, long line, int col,
 SCM_API SCM scm_cons_source (SCM xorig, SCM x, SCM y);
 SCM_INTERNAL void scm_init_srcprop (void);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_SRCPROP_H */
 
diff --git a/libguile/srfi-1.h b/libguile/srfi-1.h
index 47607bc..ba5df77 100644
--- a/libguile/srfi-1.h
+++ b/libguile/srfi-1.h
@@ -24,6 +24,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_INTERNAL SCM scm_srfi1_append_reverse (SCM revhead, SCM tail);
 SCM_INTERNAL SCM scm_srfi1_append_reverse_x (SCM revhead, SCM tail);
 SCM_INTERNAL SCM scm_srfi1_concatenate (SCM lstlst);
@@ -47,4 +51,8 @@ SCM_INTERNAL SCM scm_srfi1_remove_x (SCM pred, SCM list);
 SCM_INTERNAL void scm_register_srfi_1 (void);
 SCM_INTERNAL void scm_init_srfi_1 (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* SCM_SRFI_1_H */
diff --git a/libguile/srfi-13.h b/libguile/srfi-13.h
index 325e222..bbe1fe0 100644
--- a/libguile/srfi-13.h
+++ b/libguile/srfi-13.h
@@ -24,6 +24,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API SCM scm_string_null_p (SCM s);
 SCM_API SCM scm_string_any (SCM pred, SCM s, SCM start, SCM end);
 SCM_API SCM scm_string_every (SCM pred, SCM s, SCM start, SCM end);
@@ -117,4 +121,8 @@ SCM_API SCM scm_string_delete (SCM char_pred, SCM s, SCM start, SCM end);
 SCM_INTERNAL void scm_init_srfi_13 (void);
 SCM_INTERNAL void scm_init_srfi_13_14 (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* SCM_SRFI_13_H */
diff --git a/libguile/srfi-14.h b/libguile/srfi-14.h
index dc9718d..b508f68 100644
--- a/libguile/srfi-14.h
+++ b/libguile/srfi-14.h
@@ -24,6 +24,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct
 {
   scm_t_wchar lo;
@@ -122,4 +126,8 @@ SCM_API SCM scm_char_set_full;
 
 SCM_INTERNAL void scm_init_srfi_14 (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* SCM_SRFI_14_H */
diff --git a/libguile/srfi-4.h b/libguile/srfi-4.h
index f56c3f3..b662dee 100644
--- a/libguile/srfi-4.h
+++ b/libguile/srfi-4.h
@@ -23,6 +23,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API SCM scm_make_srfi_4_vector (SCM type, SCM len, SCM fill);
 
 
@@ -276,4 +280,8 @@ SCM_API double *scm_c64vector_writable_elements (SCM uvec,
 
 SCM_INTERNAL void scm_init_srfi_4 (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* SCM_SRFI_4_H */
diff --git a/libguile/srfi-60.h b/libguile/srfi-60.h
index 013820f..c842c27 100644
--- a/libguile/srfi-60.h
+++ b/libguile/srfi-60.h
@@ -24,6 +24,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_INTERNAL SCM scm_srfi60_log2_binary_factors (SCM n);
 SCM_INTERNAL SCM scm_srfi60_copy_bit (SCM index, SCM n, SCM bit);
 SCM_INTERNAL SCM scm_srfi60_rotate_bit_field (SCM n, SCM count, SCM start, SCM end);
@@ -34,4 +38,8 @@ SCM_INTERNAL SCM scm_srfi60_list_to_integer (SCM lst);
 SCM_INTERNAL void scm_register_srfi_60 (void);
 SCM_INTERNAL void scm_init_srfi_60 (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* SCM_SRFI_60_H */
diff --git a/libguile/stackchk.h b/libguile/stackchk.h
index 23dbdba..aeacf53 100644
--- a/libguile/stackchk.h
+++ b/libguile/stackchk.h
@@ -28,6 +28,10 @@
 #include "libguile/continuations.h"
 #include "libguile/debug.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* With debug options we have the possibility to disable stack checking.
@@ -62,6 +66,10 @@ SCM_API void scm_stack_report (void);
 SCM_API SCM scm_sys_get_stack_size (void);
 SCM_INTERNAL void scm_init_stackchk (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_STACKCHK_H */
 
 /*
diff --git a/libguile/stacks.h b/libguile/stacks.h
index ba97e08..9d0d571 100644
--- a/libguile/stacks.h
+++ b/libguile/stacks.h
@@ -26,6 +26,10 @@
 #include "libguile/__scm.h"
 #include "libguile/frames.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* {Frames and stacks}
  */
 
@@ -57,6 +61,10 @@ SCM_API SCM scm_stack_length (SCM stack);
 
 SCM_INTERNAL void scm_init_stacks (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_STACKS_H */
 
 /*
diff --git a/libguile/stime.h b/libguile/stime.h
index e41f797..848affb 100644
--- a/libguile/stime.h
+++ b/libguile/stime.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API long scm_c_time_units_per_second;
@@ -45,6 +49,10 @@ SCM_API SCM scm_strftime (SCM format, SCM stime);
 SCM_API SCM scm_strptime (SCM format, SCM string);
 SCM_INTERNAL void scm_init_stime (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_STIME_H */
 
 /*
diff --git a/libguile/strings.h b/libguile/strings.h
index 130c436..fc480db 100644
--- a/libguile/strings.h
+++ b/libguile/strings.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* String representation.
@@ -244,6 +248,10 @@ SCM_API SCM scm_sys_stringbuf_hist (void);
 
 SCM_INTERNAL void scm_init_strings (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_STRINGS_H */
 
 /*
diff --git a/libguile/strorder.h b/libguile/strorder.h
index 2c004e4..113ef5d 100644
--- a/libguile/strorder.h
+++ b/libguile/strorder.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_string_equal_p (SCM s1, SCM s2);
@@ -39,6 +43,10 @@ SCM_API SCM scm_string_ci_gr_p (SCM s1, SCM s2);
 SCM_API SCM scm_string_ci_geq_p (SCM s1, SCM s2);
 SCM_INTERNAL void scm_init_strorder (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_STRORDER_H */
 
 /*
diff --git a/libguile/strports.h b/libguile/strports.h
index b4bafdf..a00850c 100644
--- a/libguile/strports.h
+++ b/libguile/strports.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 
@@ -57,6 +61,10 @@ SCM_API SCM scm_eval_string (SCM string);
 SCM_API SCM scm_eval_string_in_module (SCM string, SCM module);
 SCM_INTERNAL void scm_init_strports (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_STRPORTS_H */
 
 /*
diff --git a/libguile/struct.h b/libguile/struct.h
index e8db316..45b95b7 100644
--- a/libguile/struct.h
+++ b/libguile/struct.h
@@ -26,6 +26,10 @@
 #include "libguile/__scm.h"
 #include "libguile/print.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* The relationship between a struct and its vtable is a bit complicated,
@@ -195,6 +199,10 @@ SCM_INTERNAL SCM scm_i_alloc_struct (scm_t_bits *vtable_data, int n_words);
 SCM_INTERNAL void scm_i_struct_inherit_vtable_magic (SCM vtable, SCM obj);
 SCM_INTERNAL void scm_init_struct (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_STRUCT_H */
 
 /*
diff --git a/libguile/symbols.h b/libguile/symbols.h
index f345e70..05e51ef 100644
--- a/libguile/symbols.h
+++ b/libguile/symbols.h
@@ -24,6 +24,11 @@
 \f
 
 #include "libguile/__scm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 #define scm_is_symbol(x)            (SCM_HAS_TYP7 (x, scm_tc7_symbol))
@@ -95,6 +100,10 @@ SCM_INTERNAL unsigned long scm_i_hash_symbol (SCM obj, unsigned long n,
 SCM_INTERNAL void scm_symbols_prehistory (void);
 SCM_INTERNAL void scm_init_symbols (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_SYMBOLS_H */
 
 /*
diff --git a/libguile/tags.h b/libguile/tags.h
index a5082f8..65acd90 100644
--- a/libguile/tags.h
+++ b/libguile/tags.h
@@ -31,6 +31,10 @@
 /* picks up scmconfig.h too */
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* In the beginning was the Word:
@@ -664,6 +668,10 @@ enum scm_tc8_tags
 
 \f
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_TAGS_H */
 
 /*
diff --git a/libguile/threads.h b/libguile/threads.h
index 6b85baf..cb61bbc 100644
--- a/libguile/threads.h
+++ b/libguile/threads.h
@@ -40,6 +40,10 @@
 #include "libguile/null-threads.h"
 #endif
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* smob tags for the thread datatypes */
@@ -230,6 +234,10 @@ SCM_API unsigned long scm_std_usleep (unsigned long);
 SCM_API SCM scm_total_processor_count (void);
 SCM_API SCM scm_current_processor_count (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_THREADS_H */
 
 /*
diff --git a/libguile/throw.h b/libguile/throw.h
index e2da731..5b9e932 100644
--- a/libguile/throw.h
+++ b/libguile/throw.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 typedef SCM (*scm_t_catch_body) (void *data);
@@ -92,6 +96,10 @@ SCM_API void scm_report_out_of_memory (void);
 SCM_API SCM scm_throw (SCM key, SCM args);
 SCM_INTERNAL void scm_init_throw (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_THROW_H */
 
 /*
diff --git a/libguile/trees.h b/libguile/trees.h
index 70d32ad..b86ca6c 100644
--- a/libguile/trees.h
+++ b/libguile/trees.h
@@ -26,6 +26,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_copy_tree (SCM obj);
@@ -36,6 +40,10 @@ SCM_API SCM scm_copy_tree (SCM obj);
 
 SCM_INTERNAL void scm_init_trees (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_TREES_H */
 
 /*
diff --git a/libguile/unicode.h b/libguile/unicode.h
index 88261c1..2c67c2e 100644
--- a/libguile/unicode.h
+++ b/libguile/unicode.h
@@ -24,10 +24,18 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_INTERNAL SCM scm_formal_name_to_char (SCM);
 SCM_INTERNAL SCM scm_char_to_formal_name (SCM);
 SCM_INTERNAL void scm_init_unicode (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_UNICODE_H */
 
 /*
diff --git a/libguile/uniform.h b/libguile/uniform.h
index ad8428f..1d3f090 100644
--- a/libguile/uniform.h
+++ b/libguile/uniform.h
@@ -26,6 +26,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /*
@@ -46,6 +50,9 @@ SCM_API void *scm_array_handle_uniform_writable_elements (scm_t_array_handle *h)
 
 SCM_INTERNAL void scm_init_uniform (void);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_UNIFORM_H */
 
diff --git a/libguile/validate.h b/libguile/validate.h
index 516a6f7..3a350d0 100644
--- a/libguile/validate.h
+++ b/libguile/validate.h
@@ -26,6 +26,10 @@
 
 \f
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define SCM_SYSERROR do { scm_syserror (FUNC_NAME); } while (0)
 
 #define SCM_MEMORY_ERROR do { scm_memory_error (FUNC_NAME); } while (0)
@@ -387,6 +391,10 @@
   } while (0)
 
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_VALIDATE_H */
 
 /*
diff --git a/libguile/values.h b/libguile/values.h
index 3dbd0b7..22dc483 100644
--- a/libguile/values.h
+++ b/libguile/values.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 SCM_API SCM scm_values_vtable;
 
 #define SCM_VALUESP(x) (SCM_STRUCTP (x)\
@@ -38,6 +42,10 @@ SCM_API size_t scm_c_nvalues (SCM obj);
 SCM_API SCM scm_c_value_ref (SCM obj, size_t idx);
 SCM_INTERNAL void scm_init_values (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_VALUES_H */
 
 /*
diff --git a/libguile/variable.h b/libguile/variable.h
index c024c85..5a94478 100644
--- a/libguile/variable.h
+++ b/libguile/variable.h
@@ -26,6 +26,10 @@
 #include "libguile/__scm.h"
 #include "libguile/smob.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* Variables 
@@ -49,6 +53,10 @@ SCM_INTERNAL void scm_i_variable_print (SCM var, SCM port, scm_print_state *psta
 
 SCM_INTERNAL void scm_init_variable (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_VARIABLE_H */
 
 /*
diff --git a/libguile/vectors.h b/libguile/vectors.h
index 995f64f..205c907 100644
--- a/libguile/vectors.h
+++ b/libguile/vectors.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_vector_p (SCM x);
@@ -73,6 +77,10 @@ SCM_INTERNAL SCM  scm_i_vector_equal_p (SCM x, SCM y);
 
 SCM_INTERNAL void scm_init_vectors (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_VECTORS_H */
 
 /*
diff --git a/libguile/vm-builtins.h b/libguile/vm-builtins.h
index 5e31a04..3807362 100644
--- a/libguile/vm-builtins.h
+++ b/libguile/vm-builtins.h
@@ -19,6 +19,10 @@
 #ifndef _SCM_VM_BUILTINS_H_
 #define _SCM_VM_BUILTINS_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifdef BUILDING_LIBGUILE
 
 #define FOR_EACH_VM_BUILTIN(M) \
@@ -44,4 +48,8 @@ SCM_INTERNAL void scm_init_vm_builtin_properties (void);
 
 #endif /* BUILDING_LIBGUILE */
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _SCM_VM_BUILTINS_H_ */
diff --git a/libguile/vm-expand.h b/libguile/vm-expand.h
index 787223d..3bc6176 100644
--- a/libguile/vm-expand.h
+++ b/libguile/vm-expand.h
@@ -16,6 +16,10 @@
  * 02110-1301 USA
  */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifndef VM_LABEL
 #define VM_LABEL(tag) l_##tag
 #define VM_OPCODE(tag) scm_op_##tag
@@ -72,6 +76,10 @@
 #endif /* VM_INSTRUCTION_TO_LABEL */
 #endif /* VM_INSTRUCTION_TO_TABLE */
 
+#ifdef __cplusplus
+}
+#endif
+
 /*
   Local Variables:
   c-file-style: "gnu"
diff --git a/libguile/vm.h b/libguile/vm.h
index 8f88d0c..0eaff4a 100644
--- a/libguile/vm.h
+++ b/libguile/vm.h
@@ -22,6 +22,10 @@
 #include <libguile.h>
 #include <libguile/programs.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 enum {
   SCM_VM_APPLY_HOOK,
   SCM_VM_PUSH_CONTINUATION_HOOK,
@@ -107,6 +111,10 @@ SCM_INTERNAL void scm_i_vm_cont_print (SCM x, SCM port,
 SCM_INTERNAL void scm_bootstrap_vm (void);
 SCM_INTERNAL void scm_init_vm (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _SCM_VM_H_ */
 
 /*
diff --git a/libguile/vports.h b/libguile/vports.h
index ae64dd4..b333408 100644
--- a/libguile/vports.h
+++ b/libguile/vports.h
@@ -25,11 +25,19 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 SCM_API SCM scm_make_soft_port (SCM pv, SCM modes);
 SCM_INTERNAL void scm_init_vports (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_VPORTS_H */
 
 /*
diff --git a/libguile/weak-set.h b/libguile/weak-set.h
index 86781c7..c220949 100644
--- a/libguile/weak-set.h
+++ b/libguile/weak-set.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* The weak set API is currently only used internally.  We could make it
@@ -60,6 +64,10 @@ SCM_INTERNAL SCM scm_weak_set_map_to_list (SCM proc, SCM set);
 SCM_INTERNAL void scm_i_weak_set_print (SCM exp, SCM port, scm_print_state *pstate);
 SCM_INTERNAL void scm_init_weak_set (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_WEAK_SET_H */
 
 /*
diff --git a/libguile/weak-table.h b/libguile/weak-table.h
index f516c26..7801e18 100644
--- a/libguile/weak-table.h
+++ b/libguile/weak-table.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 
 /* The weak table API is currently only used internally.  We could make it
@@ -85,6 +89,10 @@ SCM_INTERNAL void scm_i_weak_table_print (SCM exp, SCM port, scm_print_state *ps
 SCM_INTERNAL void scm_weak_table_prehistory (void);
 SCM_INTERNAL void scm_init_weak_table (void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  /* SCM_WEAK_TABLE_H */
 
 /*
diff --git a/libguile/weak-vector.h b/libguile/weak-vector.h
index 11395a5..3b7d94c 100644
--- a/libguile/weak-vector.h
+++ b/libguile/weak-vector.h
@@ -25,6 +25,10 @@
 
 #include "libguile/__scm.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 \f
 /* Weak vectors.  */
 
@@ -45,6 +49,9 @@ SCM_API void scm_c_weak_vector_set_x (SCM v, size_t k, SCM x);
 
 SCM_INTERNAL void scm_init_weak_vectors (void);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* SCM_WEAK_VECTOR_H */
 
diff --git a/libguile/win32-uname.h b/libguile/win32-uname.h
index 4b74981..53790d2 100644
--- a/libguile/win32-uname.h
+++ b/libguile/win32-uname.h
@@ -21,6 +21,10 @@
  * 02110-1301 USA
  */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define _UTSNAME_LENGTH 65
 #define _UTSNAME_NODENAME_LENGTH _UTSNAME_LENGTH
 #define _UTSNAME_DOMAIN_LENGTH _UTSNAME_LENGTH
@@ -49,4 +53,8 @@ struct utsname
 
 int uname (struct utsname * uts);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* SCM_WIN32_UNAME_H */
-- 
2.3.6




^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] Add C++ extern "C" guards to internal headers.
  2015-07-14 18:07 ` [PATCH 2/3] Add C++ extern "C" guards to internal headers Taahir Ahmed
@ 2015-07-14 19:36   ` Andreas Rottmann
  2015-07-16  0:22     ` Taahir Ahmed
  0 siblings, 1 reply; 10+ messages in thread
From: Andreas Rottmann @ 2015-07-14 19:36 UTC (permalink / raw)
  To: Taahir Ahmed; +Cc: guile-devel

Taahir Ahmed <ahmed.taahir@gmail.com> writes:

> ---
>  libguile/__scm.h               |  8 ++++++++
>  [...]
>
> diff --git a/libguile/__scm.h b/libguile/__scm.h
> index 31e3952..1967069 100644
> --- a/libguile/__scm.h
> +++ b/libguile/__scm.h
> @@ -53,6 +53,10 @@
>  /* What did the configure script discover about the outside world?  */
>  #include "libguile/scmconfig.h"
>  
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
>
>  \f
>  
>  /* {Compiler hints}
> @@ -523,6 +527,10 @@ typedef long SCM_STACKITEM;
>  # define SCM_THREAD_LOCAL
>  #endif
>  
> +#ifdef __cplusplus
> +}
> +#endif
> +
>  #endif  /* SCM___SCM_H */
>
Just a minor nitpick: it might make sense to add a pair of macros to
libguile/__scm.h for the '#ifdef __cplusplus' dance, so these
boilerplate additions become just two lines, e.g.:

+ SCM_BEGIN_DECLS

...

+ SCM_END_DECLS

This is done in GLib, for example, and cuts down the noise a bit.

Regards, Rotty
-- 
Andreas Rottmann -- <http://rotty.xx.vu/>



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/3] Implement Guile exceptions with C++ exceptions.
  2015-07-14 18:07 Prototype for C++-compatible Guile Exceptions Taahir Ahmed
  2015-07-14 18:07 ` [PATCH 1/3] Support C++ source files, use -fexceptions Taahir Ahmed
  2015-07-14 18:07 ` [PATCH 2/3] Add C++ extern "C" guards to internal headers Taahir Ahmed
@ 2015-07-15  3:40 ` Taahir Ahmed
  2015-08-10  3:26 ` Prototype for C++-compatible Guile Exceptions Taahir Ahmed
  2015-09-04  8:06 ` Mark H Weaver
  4 siblings, 0 replies; 10+ messages in thread
From: Taahir Ahmed @ 2015-07-15  3:40 UTC (permalink / raw)
  To: guile-devel; +Cc: Taahir Ahmed

eh-jmp.{h,cc} contain setjmp/longjmp analogues that use C++ exceptions
to unwind the stack.  This means that C++ destructors will be called
properly in when a guile exception passes through a user code frame.

Flow control to resume a continuation remains implemented with
setjmp/longjmp, since it appears that in some places the jump travels
down the stack.
---
 libguile/Makefile.am                          |  1 +
 libguile/control.c                            |  6 ++-
 libguile/eh-jmp.cc                            | 39 ++++++++++++++
 libguile/eh-jmp.h                             | 23 ++++++++
 libguile/eval.c                               | 35 +++++++++---
 libguile/threads.h                            |  5 --
 libguile/throw.c                              | 34 +++++++++---
 libguile/vm-engine.c                          |  5 +-
 libguile/vm.c                                 | 57 ++++++++++++++++----
 test-suite/standalone/Makefile.am             |  7 +++
 test-suite/standalone/test-cpp-destructors.cc | 77 
+++++++++++++++++++++++++++
 11 files changed, 259 insertions(+), 30 deletions(-)
 create mode 100644 libguile/eh-jmp.cc
 create mode 100644 libguile/eh-jmp.h
 create mode 100644 test-suite/standalone/test-cpp-destructors.cc

diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index cc88215..f5e746f 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -140,6 +140,7 @@ libguile_@GUILE_EFFECTIVE_VERSION@_la_SOURCES =			
	\
 	deprecation.c				\
 	dynstack.c				\
 	dynwind.c				\
+	eh-jmp.cc				\
 	eq.c					\
 	error.c					\
 	eval.c					\
diff --git a/libguile/control.c b/libguile/control.c
index 347d697..53e3241 100644
--- a/libguile/control.c
+++ b/libguile/control.c
@@ -24,6 +24,7 @@
 
 #include "libguile/_scm.h"
 #include "libguile/control.h"
+#include "libguile/eh-jmp.h"
 #include "libguile/programs.h"
 #include "libguile/instructions.h"
 #include "libguile/vm.h"
@@ -37,7 +38,8 @@
 \f
 
 
-/* Only to be called if the SCM_I_SETJMP returns 1 */
+/* Only to be called if we are returning to a prompt via nonlocal
+   jump. */
 SCM
 scm_i_prompt_pop_abort_args_x (struct scm_vm *vp)
 {
@@ -177,7 +179,7 @@ scm_c_abort (struct scm_vm *vp, SCM tag, size_t n, SCM 
*argv,
     *(++(vp->sp)) = scm_from_size_t (n+1); /* +1 for continuation */
 
   /* Jump! */
-  SCM_I_LONGJMP (*registers, 1);
+  eh_throw (tag);
 
   /* Shouldn't get here */
   abort ();
diff --git a/libguile/eh-jmp.cc b/libguile/eh-jmp.cc
new file mode 100644
index 0000000..f5b7b80
--- /dev/null
+++ b/libguile/eh-jmp.cc
@@ -0,0 +1,39 @@
+#include "libguile/eh-jmp.h"
+
+struct prompt_exception
+{
+  SCM tag;
+};
+
+int eh_catch (SCM *taglist, tryfn_scm fn, SCM *result, ...)
+{
+  va_list ap;
+  va_start (ap, result);
+
+  try
+    {
+      *result = fn (ap);
+      va_end (ap);
+      return 0;
+    }
+  catch (prompt_exception e)
+    {
+      va_end(ap);
+
+      for (SCM rest = *taglist; rest != SCM_EOL; rest = scm_cdr (rest))
+        {
+          SCM cur_key = scm_car (rest);
+
+          if (scm_is_eq (cur_key, e.tag))
+            return 1;
+        }
+
+      throw e;
+    }
+}
+
+void eh_throw(SCM tag)
+{
+  prompt_exception e = {tag};
+  throw e;
+}
diff --git a/libguile/eh-jmp.h b/libguile/eh-jmp.h
new file mode 100644
index 0000000..6730895
--- /dev/null
+++ b/libguile/eh-jmp.h
@@ -0,0 +1,23 @@
+#ifndef LIBGUILE_EH_JMP_H
+#define LIBGUILE_EH_JMP_H
+
+#include <stdarg.h>
+
+#include "libguile/__scm.h"
+#include "libguile/_scm.h"
+#include "libguile/pairs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef SCM (* tryfn_scm) (va_list);
+
+int  eh_catch (SCM *taglist, tryfn_scm fn, SCM *result, ...);
+void eh_throw (SCM taglist) SCM_NORETURN;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libguile/eval.c b/libguile/eval.c
index 735e6c0..c83b7e7 100644
--- a/libguile/eval.c
+++ b/libguile/eval.c
@@ -37,6 +37,7 @@
 #include "libguile/debug.h"
 #include "libguile/deprecation.h"
 #include "libguile/dynwind.h"
+#include "libguile/eh-jmp.h"
 #include "libguile/eq.h"
 #include "libguile/expand.h"
 #include "libguile/feature.h"
@@ -238,6 +239,8 @@ truncate_values (SCM x)
 }
 #define EVAL1(x, env) (truncate_values (eval ((x), (env))))
 
+static SCM try_call_with_prompt(va_list ap);
+
 static SCM
 eval (SCM x, SCM env)
 {
@@ -424,13 +427,14 @@ eval (SCM x, SCM env)
     case SCM_M_CALL_WITH_PROMPT:
       {
         struct scm_vm *vp;
-        SCM k, res;
+        SCM tag, res;
+        SCM taglist;
         scm_i_jmp_buf registers;
         /* We need the handler after nonlocal return to the setjmp, so
            make sure it is volatile.  */
         volatile SCM handler;
 
-        k = EVAL1 (CAR (mx), env);
+        tag = EVAL1 (CAR (mx), env);
         handler = EVAL1 (CDDR (mx), env);
         vp = scm_the_vm ();
 
@@ -438,13 +442,15 @@ eval (SCM x, SCM env)
         scm_dynstack_push_prompt (&SCM_I_CURRENT_THREAD->dynstack,
                                   SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY
                                   | SCM_F_DYNSTACK_PROMPT_PUSH_NARGS,
-                                  k,
+                                  tag,
                                   vp->fp - vp->stack_base,
                                   vp->sp - vp->stack_base,
                                   vp->ip,
                                   &registers);
 
-        if (SCM_I_SETJMP (registers))
+        taglist = scm_cons (tag, SCM_EOL);
+        if (eh_catch (&taglist, try_call_with_prompt, &res, mx, env,
+                      &SCM_I_CURRENT_THREAD->dynstack))
           {
             /* The prompt exited nonlocally. */
             scm_gc_after_nonlocal_exit ();
@@ -453,9 +459,7 @@ eval (SCM x, SCM env)
             args = scm_i_prompt_pop_abort_args_x (vp);
             goto apply_proc;
           }
-        
-        res = scm_call_0 (eval (CADR (mx), env));
-        scm_dynstack_pop (&SCM_I_CURRENT_THREAD->dynstack);
+
         return res;
       }
 
@@ -464,6 +468,23 @@ eval (SCM x, SCM env)
     }
 }
 
+static SCM
+try_call_with_prompt(va_list ap)
+{
+  SCM res;
+  SCM mx;
+  SCM env;
+  scm_t_dynstack *dynstack;
+
+  mx       = va_arg (ap, SCM);
+  env      = va_arg (ap, SCM);
+  dynstack = va_arg (ap, scm_t_dynstack*);
+
+  res = scm_call_0 (eval (CADR (mx), env));
+  scm_dynstack_pop (dynstack);
+  return res;
+}
+
 \f
 
 /* Simple procedure calls
diff --git a/libguile/threads.h b/libguile/threads.h
index cb61bbc..1c1f0e3 100644
--- a/libguile/threads.h
+++ b/libguile/threads.h
@@ -115,11 +115,6 @@ typedef struct scm_i_thread {
   /* For keeping track of the stack and registers. */
   struct scm_vm *vp;
   SCM_STACKITEM *base;
-  scm_i_jmp_buf regs;
-#ifdef __ia64__
-  void *register_backing_store_base;
-  scm_t_contregs *pending_rbs_continuation;
-#endif
 
   /* Whether this thread is in a critical section. */
   int critical_section_level;
diff --git a/libguile/throw.c b/libguile/throw.c
index bbde5e0..f784df7 100644
--- a/libguile/throw.c
+++ b/libguile/throw.c
@@ -23,10 +23,12 @@
 #endif
 
 #include <alloca.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <unistdio.h>
 #include "libguile/_scm.h"
 #include "libguile/smob.h"
+#include "libguile/eh-jmp.h"
 #include "libguile/eval.h"
 #include "libguile/eq.h"
 #include "libguile/control.h"
@@ -69,11 +71,34 @@ static SCM throw_var;
 
 static SCM exception_handler_fluid;
 
+/* A helper function for eh_tryfn_prompt.  Indirectly invoked below in
+   catch. */
+static SCM
+call_helper (va_list ap)
+{
+  SCM res;
+  SCM thunk;
+  scm_t_dynstack *dynstack;
+  SCM dynamic_state;
+
+  thunk         = va_arg (ap, SCM);
+  dynstack      = va_arg (ap, scm_t_dynstack*);
+  dynamic_state = va_arg (ap, SCM);
+
+  res = scm_call_0 (thunk);
+
+  scm_dynstack_unwind_fluid (dynstack, dynamic_state);
+  scm_dynstack_pop (dynstack);
+
+  return res;
+}
+
 static SCM
 catch (SCM tag, SCM thunk, SCM handler, SCM pre_unwind_handler)
 {
   struct scm_vm *vp;
   SCM eh, prompt_tag;
+  SCM taglist;
   SCM res;
   scm_t_dynstack *dynstack = &SCM_I_CURRENT_THREAD->dynstack;
   SCM dynamic_state = SCM_I_CURRENT_THREAD->dynamic_state;
@@ -116,7 +141,9 @@ catch (SCM tag, SCM thunk, SCM handler, SCM 
pre_unwind_handler)
   scm_dynstack_push_fluid (dynstack, exception_handler_fluid, eh,
                            dynamic_state);
 
-  if (SCM_I_SETJMP (registers))
+  taglist = scm_cons (prompt_tag, SCM_EOL);
+  if (eh_catch (&taglist, call_helper, &res, thunk, dynstack,
+               dynamic_state))
     {
       /* A non-local return.  */
       SCM args;
@@ -133,11 +160,6 @@ catch (SCM tag, SCM thunk, SCM handler, SCM 
pre_unwind_handler)
       return scm_apply_0 (handler, args);
     }
 
-  res = scm_call_0 (thunk);
-
-  scm_dynstack_unwind_fluid (dynstack, dynamic_state);
-  scm_dynstack_pop (dynstack);
-
   return res;
 }
 
diff --git a/libguile/vm-engine.c b/libguile/vm-engine.c
index 7e752dd..628b951 100644
--- a/libguile/vm-engine.c
+++ b/libguile/vm-engine.c
@@ -419,7 +419,7 @@
   ((scm_t_uintptr) (ptr) % alignof_type (type) == 0)
 
 static SCM
-VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
+VM_NAME (SCM *catch_taglist, scm_i_thread *thread, struct scm_vm *vp,
          scm_i_jmp_buf *registers, int resume)
 {
   /* Instruction pointer: A pointer to the opcode that is currently
@@ -2069,6 +2069,9 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
                                 LOCAL_ADDRESS (proc_slot) - vp->stack_base,
                                 ip + offset,
                                 registers);
+
+      *catch_taglist = scm_cons (LOCAL_REF (tag), *catch_taglist);
+
       NEXT (3);
     }
 
diff --git a/libguile/vm.c b/libguile/vm.c
index 0e59835..7ac6523 100644
--- a/libguile/vm.c
+++ b/libguile/vm.c
@@ -39,6 +39,7 @@
 
 #include "_scm.h"
 #include "control.h"
+#include "eh-jmp.h"
 #include "frames.h"
 #include "gc-inline.h"
 #include "instructions.h"
@@ -783,7 +784,7 @@ scm_i_call_with_current_continuation (SCM proc)
 #undef VM_USE_HOOKS
 #undef VM_NAME
 
-typedef SCM (*scm_t_vm_engine) (scm_i_thread *current_thread, struct scm_vm 
*vp,
+typedef SCM (*scm_t_vm_engine) (SCM *taglist, scm_i_thread *current_thread, 
struct scm_vm *vp,
                                 scm_i_jmp_buf *registers, int resume);
 
 static const scm_t_vm_engine vm_engines[SCM_VM_NUM_ENGINES] =
@@ -1204,6 +1205,26 @@ scm_the_vm (void)
   return thread_vm (SCM_I_CURRENT_THREAD);
 }
 
+static SCM
+try_call_engine (va_list ap)
+{
+  scm_t_vm_engine engine;
+  SCM *taglist;
+  scm_i_thread *thread;
+  struct scm_vm *vp;
+  scm_i_jmp_buf *registers;
+  int resume;
+
+  engine    = va_arg (ap, scm_t_vm_engine);
+  taglist   = va_arg (ap, SCM*);
+  thread    = va_arg (ap, scm_i_thread*);
+  vp        = va_arg (ap, struct scm_vm*);
+  registers = va_arg (ap, scm_i_jmp_buf*);
+  resume    = va_arg (ap, int);
+
+  return engine (taglist, thread, vp, registers, resume);
+}
+
 SCM
 scm_call_n (SCM proc, SCM *argv, size_t nargs)
 {
@@ -1246,16 +1267,34 @@ scm_call_n (SCM proc, SCM *argv, size_t nargs)
   vp->fp = &base[5];
 
   {
-    int resume = SCM_I_SETJMP (registers);
-      
-    if (SCM_UNLIKELY (resume))
+    int resume = 0;
+    SCM res;
+    scm_t_vm_engine engine;
+    SCM taglist;
+
+    engine = vm_engines[vp->engine];
+
+    taglist = SCM_EOL;
+
+    while (1)
       {
-        scm_gc_after_nonlocal_exit ();
-        /* Non-local return.  */
-        vm_dispatch_abort_hook (vp);
+        resume = eh_catch(/* Arguments used by eh_catch. */
+                          &taglist, try_call_engine, &res,
+                          /* Arguments consumed by try_call_engine. */
+                          engine,
+                          /* Arguments sent to the engine. */
+                          &taglist, thread, vp, &registers, resume);
+        if (resume)
+          {
+            scm_gc_after_nonlocal_exit ();
+            /* Non-local return.  */
+            vm_dispatch_abort_hook (vp);
+          }
+        else
+          {
+            return res;
+          }
       }
-
-    return vm_engines[vp->engine](thread, vp, &registers, resume);
   }
 }
 
diff --git a/test-suite/standalone/Makefile.am b/test-
suite/standalone/Makefile.am
index 5138b15..01270f9 100644
--- a/test-suite/standalone/Makefile.am
+++ b/test-suite/standalone/Makefile.am
@@ -96,6 +96,13 @@ EXTRA_DIST += test-language.el test-language.js
 check_SCRIPTS += test-guild-compile
 TESTS += test-guild-compile
 
+# test-cpp-destructors
+test_cpp_destructors_SOURCES = test-cpp-destructors.cc
+test_cpp_destructors_CFLAGS = ${test_cflags}
+test_cpp_destructors_LDADD = ${LIBGUILE_LDADD}
+check_PROGRAMS += test-cpp-destructors
+TESTS += test-cpp-destructors
+
 # test-num2integral
 test_num2integral_SOURCES = test-num2integral.c
 test_num2integral_CFLAGS = ${test_cflags}
diff --git a/test-suite/standalone/test-cpp-destructors.cc b/test-
suite/standalone/test-cpp-destructors.cc
new file mode 100644
index 0000000..99fbf32
--- /dev/null
+++ b/test-suite/standalone/test-cpp-destructors.cc
@@ -0,0 +1,77 @@
+// test-cpp-destructors.c
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <cstdlib>
+
+#include <iostream>
+
+#include <libguile.h>
+
+// Canary value to track constructor/destructor execution.
+//
+//   0: constructor has not yet run
+//
+//   1: constructor has run
+//
+//   2: destructor has run
+static int canary = 0;
+
+struct miner
+{
+    miner()
+    {
+        canary = 1;
+    }
+
+    ~miner()
+    {
+        canary = 2;
+    }
+};
+
+static SCM test_miner(void *data)
+{
+    miner bob;
+
+    SCM should_be_int = static_cast<SCM>(data);
+    int dummy = scm_to_int(should_be_int);
+
+    return SCM_BOOL_T;
+}
+
+static SCM test_miner_handler(void *data, SCM key, SCM args)
+{
+    // Do nothing.
+
+    return SCM_BOOL_T;
+}
+
+static void tests(void *data, int argc, char **argv)
+{
+    SCM test_data = scm_from_utf8_string("Ceci n'est pas un int.");
+    scm_internal_catch(
+        SCM_BOOL_T,
+        test_miner,
+        static_cast<void*>(&test_data),
+        test_miner_handler,
+        NULL
+    );
+
+    // Check if destructor ran.
+    if(canary != 2)
+    {
+        std::cerr << "Destructor was not run by guile exception." << 
std::endl;
+        std::exit(1);
+    }
+
+    std::exit(0);
+}
+
+int main(int argc,  char **argv)
+{
+    scm_boot_guile(argc, argv, tests, NULL);
+    return 0;
+}
-- 
2.3.6



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] Add C++ extern "C" guards to internal headers.
  2015-07-14 19:36   ` Andreas Rottmann
@ 2015-07-16  0:22     ` Taahir Ahmed
  2015-07-16 18:55       ` Andreas Rottmann
  0 siblings, 1 reply; 10+ messages in thread
From: Taahir Ahmed @ 2015-07-16  0:22 UTC (permalink / raw)
  To: Andreas Rottmann; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 577 bytes --]

On Tuesday 14 July 2015 21:36:31 Andreas Rottmann wrote: 
> Just a minor nitpick: it might make sense to add a pair of macros to
> libguile/__scm.h for the '#ifdef __cplusplus' dance, so these
> boilerplate additions become just two lines, e.g.:

That's a good idea, and I've gone ahead and incorporated it.  I won't
publish a new patchset here, because it doesn't really change anything.

As an aside, have you received patch 3?  It hasn't shown up in the list
archive, and I've sent it again, with no luck.  I'm unsure if it somehow
got held for moderation.

Thanks,

Taahir

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] Add C++ extern "C" guards to internal headers.
  2015-07-16  0:22     ` Taahir Ahmed
@ 2015-07-16 18:55       ` Andreas Rottmann
  0 siblings, 0 replies; 10+ messages in thread
From: Andreas Rottmann @ 2015-07-16 18:55 UTC (permalink / raw)
  To: Taahir Ahmed; +Cc: guile-devel

Taahir Ahmed <ahmed.taahir@gmail.com> writes:

> On Tuesday 14 July 2015 21:36:31 Andreas Rottmann wrote: 
>> Just a minor nitpick: it might make sense to add a pair of macros to
>> libguile/__scm.h for the '#ifdef __cplusplus' dance, so these
>> boilerplate additions become just two lines, e.g.:
>
> That's a good idea, and I've gone ahead and incorporated it.  I won't
> publish a new patchset here, because it doesn't really change anything.
>
> As an aside, have you received patch 3?  It hasn't shown up in the list
> archive, and I've sent it again, with no luck.  I'm unsure if it somehow
> got held for moderation.
>
No, it indeed hasn't reached me via the list. Is it perhaps very large?

Regards, Rotty
-- 
Andreas Rottmann -- <http://rotty.xx.vu/>



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Prototype for C++-compatible Guile Exceptions.
  2015-07-14 18:07 Prototype for C++-compatible Guile Exceptions Taahir Ahmed
                   ` (2 preceding siblings ...)
  2015-07-15  3:40 ` [PATCH 3/3] Implement Guile exceptions with C++ exceptions Taahir Ahmed
@ 2015-08-10  3:26 ` Taahir Ahmed
  2015-09-04  8:06 ` Mark H Weaver
  4 siblings, 0 replies; 10+ messages in thread
From: Taahir Ahmed @ 2015-08-10  3:26 UTC (permalink / raw)
  To: guile-devel

[-- Attachment #1: Type: text/plain, Size: 386 bytes --]

On Tuesday 14 July 2015 13:07:26 you wrote:
> I'm posting these patches to feel out the likelihood of this approach to
> C++ exception compatibility ever getting adopted into Guile.

I just wanted to ping the list to check whether C++ exception
compatibility is something desired, and if it is, whether this approach
for achieving is one that can be integrated into guile.

Taahir Ahmed

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Prototype for C++-compatible Guile Exceptions.
  2015-07-14 18:07 Prototype for C++-compatible Guile Exceptions Taahir Ahmed
                   ` (3 preceding siblings ...)
  2015-08-10  3:26 ` Prototype for C++-compatible Guile Exceptions Taahir Ahmed
@ 2015-09-04  8:06 ` Mark H Weaver
  2015-09-06 23:01   ` Taahir Ahmed
  4 siblings, 1 reply; 10+ messages in thread
From: Mark H Weaver @ 2015-09-04  8:06 UTC (permalink / raw)
  To: Taahir Ahmed; +Cc: guile-devel

Taahir Ahmed <ahmed.taahir@gmail.com> writes:

> Currently, the use of libguile functions from C++ is fraught with
> danger.  C++ destructors are not triggered by guile exceptions, and the
> dynwind mechanism is ill-suited for application to C++ data structures
> (in particular, STL structures).

I agree that we need to improve this.  Thanks for stepping forward to
work on it.  I apologize for the long delay.

> This sequence of patches addresses this shortcoming by using hidden C++
> exceptions to perform the stack unwinding when a guile exception is
> thrown, so that the pre-checking demonstrated above is not needed.

Your proposal is not unreasonable, but at the present time I feel rather
strongly that we should keep C++ and its runtime out of core Guile.  For
one thing, the C++ runtime, calling conventions, and exception model are
poorly suited to Scheme, with its more general control flow, proper tail
calls, garbage collection, etc.

Also, especially when we have native code generation, I expect it will
be highly beneficial to have complete control over our runtime, internal
calling conventions, and internal exception handling.  These
considerations argue for us to move in the direction of _fewer_
marriages to external runtime libraries rather than more.

Having said that, of course we must retain good integration with code
written in other languages and runtimes such as C and C++.

In my opinion, the best approach is to *convert* exceptions at the
boundaries between libguile and application code.  This opens the door
for us to integrate nicely not only with C++, but also with other
languages and runtimes.

In general, the approach would be to add language-specific wrappers for
all public libguile API functions.  These would arrange for Guile
exceptions thrown within libguile to be converted into whatever type of
exception or error handling is desired by the caller.

Wrappers would also be needed at the interfaces where libguile calls
back to user code.  These wrappers would do conversion in the other
direction, e.g. by catching C++ exceptions and converting them into
Guile exceptions.

I'm not sure what is the best approach to creating these wrappers, but I
guess it could be done with some combination of the C preprocessor and
snarfing tools that scrape our headers and generate code.  I guess it
will also involve adding an optional C++ library containing code needed
by the wrappers.

I'm okay with adding C++ code within "#ifdef __cplusplus" in our
headers, as long as a C++ compiler is not needed to compile libguile or
its C users.

Do you think that an approach like this would work for you?

    Regards,
      Mark



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Prototype for C++-compatible Guile Exceptions.
  2015-09-04  8:06 ` Mark H Weaver
@ 2015-09-06 23:01   ` Taahir Ahmed
  0 siblings, 0 replies; 10+ messages in thread
From: Taahir Ahmed @ 2015-09-06 23:01 UTC (permalink / raw)
  To: Mark H Weaver; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 1467 bytes --]

Mark H Weaver writes:
> Your proposal is not unreasonable, but at the present time I feel
> rather strongly that we should keep C++ and its runtime out of core
> Guile.  For one thing, the C++ runtime, calling conventions, and
> exception model are poorly suited to Scheme, with its more general
> control flow, proper tail calls, garbage collection, etc.
> 
> Also, especially when we have native code generation, I expect it will
> be highly beneficial to have complete control over our runtime,
> internal calling conventions, and internal exception handling.  These
> considerations argue for us to move in the direction of _fewer_
> marriages to external runtime libraries rather than more.

I'm certainly not wedded to this strategy --- I just figured that it
would be better to have something concrete rather than just getting on
the list and complaining.

> In general, the approach would be to add language-specific wrappers
> for all public libguile API functions.  These would arrange for Guile
> exceptions thrown within libguile to be converted into whatever type
> of exception or error handling is desired by the caller.
>
> ...
>
> Do you think that an approach like this would work for you?

That does sound interesting, and it seems like something I would be
interested to work on in my spare time.  I'm sure that there will be
many pain points, but there is no point in trying to predict them ahead
of time.

Taahir

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 472 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2015-09-06 23:01 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-14 18:07 Prototype for C++-compatible Guile Exceptions Taahir Ahmed
2015-07-14 18:07 ` [PATCH 1/3] Support C++ source files, use -fexceptions Taahir Ahmed
2015-07-14 18:07 ` [PATCH 2/3] Add C++ extern "C" guards to internal headers Taahir Ahmed
2015-07-14 19:36   ` Andreas Rottmann
2015-07-16  0:22     ` Taahir Ahmed
2015-07-16 18:55       ` Andreas Rottmann
2015-07-15  3:40 ` [PATCH 3/3] Implement Guile exceptions with C++ exceptions Taahir Ahmed
2015-08-10  3:26 ` Prototype for C++-compatible Guile Exceptions Taahir Ahmed
2015-09-04  8:06 ` Mark H Weaver
2015-09-06 23:01   ` Taahir Ahmed

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).