[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Failing to run Foreign Object example

From: Matt Wette
Subject: Re: Failing to run Foreign Object example
Date: Sun, 4 Aug 2019 15:23:34 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0

On 8/4/19 3:13 PM, Martin Michel wrote:
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


#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;

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);

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);

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);


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;

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 (&register_functions, NULL);
   scm_shell (argc, argv);

I don't see you calling init_image_type.  Maybe try that in main_prog.

Also, try "gcc -g" instead of "gcc" and "gdb foreign" followed by "run" instead of 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]