guile-user
[Top][All Lists]
Advanced

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

Failing to run Foreign Object example


From: Martin Michel
Subject: Failing to run Foreign Object example
Date: Mon, 5 Aug 2019 00:13:52 +0200
User-agent: Mutt/1.5.21 (2010-09-15)

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



reply via email to

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