Hi there, I want to extend a C++ program with Guile, mainly for configuration and parameter scripting. For this, I need access class objects and methods. I could not found simple examples so I started to experiment with Smobs and only by chance find out that they are deprecated in favour of foreign object. Unfortunately I am stuck very early. I just want to implement the example from the documentation; I assembled the snippets and compiled it. But it fails to run the simple test and terminates with Segmentation Fault.
What have I done wrong? My build and interaction: ------------------------- $ gcc `guile-config compile` -c foreign.c $ gcc foreign.o `guile-config link` -o foreign $ ./foreign GNU Guile 2.2.6 Copyright (C) 1995-2019 Free Software Foundation, Inc. Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. This program is free software, and you are welcome to redistribute it under certain conditions; type `,show c' for details. Enter `,help' for help. scheme@(guile-user)> make-image $1 = #<procedure make-image (_ _ _)> scheme@(guile-user)> (make-image "Whistler's Mother" 100 100) Segmentation fault foreign.c: ---------- #include <libguile.h> static void main_prog (void *closure, int argc, char *argv[]); struct image { int width, height; char *pixels; /* The name of this image */ SCM name; /* A function to call when this image is modified, e.g., to update the screen, or SCM_BOOL_F if no action necessary */ SCM update_func; }; static SCM image_type; void init_image_type (void) { SCM name, slots; scm_t_struct_finalize finalizer; name = scm_from_utf8_symbol ("image"); slots = scm_list_1 (scm_from_utf8_symbol ("data")); finalizer = NULL; image_type = scm_make_foreign_object_type (name, slots, finalizer); } SCM make_image (SCM name, SCM s_width, SCM s_height) { struct image *image; int width = scm_to_int (s_width); int height = scm_to_int (s_height); /* Allocate the `struct image'. Because we use scm_gc_malloc, this memory block will be automatically reclaimed when it becomes inaccessible, and its members will be traced by the garbage collector. */ image = (struct image *) scm_gc_malloc (sizeof (struct image), "image"); image->width = width; image->height = height; /* Allocating the pixels with scm_gc_malloc_pointerless means that the pixels data is collectable by GC, but that GC shouldn't spend time tracing its contents for nested pointers because there aren't any. */ image->pixels = scm_gc_malloc_pointerless (width * height, "image pixels"); image->name = name; image->update_func = SCM_BOOL_F; /* Now wrap the struct image* in a new foreign object, and return that object. */ return scm_make_foreign_object_1 (image_type, image); } SCM clear_image (SCM image_obj) { int area; struct image *image; scm_assert_foreign_object_type (image_type, image_obj); image = scm_foreign_object_ref (image_obj, 0); area = image->width * image->height; memset (image->pixels, 0, area); /* Invoke the image's update function. */ if (scm_is_true (image->update_func)) scm_call_0 (image->update_func); return SCM_UNSPECIFIED; } static void * register_functions (void *data) { scm_c_define_gsubr ("make-image", 3, 0, 0, make_image); scm_c_define_gsubr ("clear-image", 1, 0, 0, clear_image); return NULL; } int main (int argc, char *argv[]) { scm_boot_guile (argc, argv, main_prog, 0); return 0; } static void main_prog (void *closure, int argc, char *argv[]) { scm_with_guile (®ister_functions, NULL); scm_shell (argc, argv); }