emacs-devel
[Top][All Lists]
Advanced

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

studying emacs internals


From: Scott Lanning
Subject: studying emacs internals
Date: Sat, 1 Dec 2001 21:46:42 -0500

Hello, I've begun learning emacs internals in the past
couple weeks. Now I'm learning how vectors/pseudovectors
work, like `frame', `window', etc.. To that end, I'm making
a similar minimal object, called `mystruct'.
`mystruct' is a C structure that hides in a vector, basically.

Mostly I have it done. But, now I found I want to deallocate
the structure. Here is some elisp that uses the DEFUNs that
I made:

  ;; Allocate the struct
  (setq mystruct (create-mystruct))

  ;; Set i member of mystruct
  (set-mystruct-i mystruct 134217727)

  ;; Check that it really set i
  (mystruct-i mystruct)

  ;; Nicely free the memory of the struct
  (delete-mystruct mystruct)

The problem is the final call, I would like the
variable mystruct to be void (I think, maybe not?),
like before it was created with setq. I tried calling
Fset(mystruct, Qunbound), but mystruct isn't a symbol.
I'm confused at this point.


Here is the C code for reference. Please make comments
on it also if you want to. Thanks for any input.



/* This is a study of the emacs internals interface
   between C structs and Elisp. */

#include "config.h"
#include "lisp.h"


/* c.f. syms_of_mystruct() at bottom */
Lisp_Object Qmystructp;


/* An example struct, it could be any struct you want.
   It's similar in many ways to `frame', `window', etc. */
struct mystruct
{
  /* The first two fields are the header of a vector,
     and they're basically here to take up space. */
  EMACS_INT size;
  struct Lisp_Vector *next;
  /* Put all your struct data below here. */
  EMACS_INT i;
  EMACS_INT *j;
};

typedef struct mystruct MYSTRUCT;
typedef struct mystruct *MYSTRUCT_PTR;

#define XMYSTRUCT(p) (eassert (GC_VECTORP(p)),(MYSTRUCT_PTR) XPNTR (p))
#define XSETMYSTRUCT(a, b) (XSETVECTOR (a, b))

#define CHECK_MYSTRUCT(x, i)                                       \
     do {                                                          \
       if (! VECTORP (x))                                          \
         x = wrong_type_argument (Qmystructp, (x));                \
     } while (0)


/*
  ALLOCATING MEMORY
  allocate_mystruct() and make_mystruct() follow the
  examples of allocate_window() and make_window().
  allocate_mystruct() allocates a vector (normally containing
  Lisp_Objects, but can also be thought of as a space of memory
  allocated in Lisp_Object-sized quanta :)) that is big enough to
  contain a `mystruct' struct, then make_mystruct() returns the
  corresponding Lisp_Object.
*/

MYSTRUCT_PTR
allocate_mystruct ()
{
  EMACS_INT len = VECSIZE (MYSTRUCT);
  struct Lisp_Vector *v = allocate_vector (len);
  EMACS_INT n;

  /* zero out contents */
  for (n = 0; n < len; ++n)
    v->contents[n] = make_number (0);
  v->size = len;

  return (MYSTRUCT_PTR) v;
}

DEFUN ("create-mystruct", Fcreate_mystruct, Screate_mystruct, 0, 2, 0,
  "Create a Lisp_Object holding a mystruct. The two arguments\n\
I and J set the corresponding integer values in the mystruct.")
     (i_obj, j_obj)
     Lisp_Object i_obj, j_obj;
{
  MYSTRUCT_PTR m;
  Lisp_Object mystruct;

  m = allocate_mystruct ();
  m->j = (int *) xmalloc(sizeof(int));

  if (INTEGERP (i_obj))
    m->i = XINT (i_obj);

  if (INTEGERP (j_obj))
    *m->j = XINT (j_obj);
  else
    *m->j = 0;

  XSETMYSTRUCT (mystruct, m);
  return mystruct;
}


/*
  FREEING MEMORY
  Depending on the struct, the global variables holding
  the state, dependence on other structs (a window is concerned
  about its parent window, its frame...), what hooks need run,
  etc., this can be a faily complex function. Be sure to
  xfree() any pointers to allocated memory.
  allocate_vector(), which calls allocate_vectorlike(),
  uses lisp_malloc() to allocate the memory. From comments in
  alloc.c, I think that implies that lisp_free() will eventually
  be called by the garbage collector when the Lisp_Vector
  is no longer used by anything.
  For an example, see Fdelete_frame().
*/

DEFUN ("delete-mystruct", Fdelete_mystruct, Sdelete_mystruct, 1, 1, 0,
  "Free MYSTRUCT")
     (mystruct)
     Lisp_Object mystruct;
{
  MYSTRUCT_PTR m;
  Lisp_Object sym;

  CHECK_MYSTRUCT (mystruct, 0);
  m = XMYSTRUCT (mystruct);

  /* free what we allocated */
  if (m->j)
    xfree (m->j);

  /* Here's an example of how to run a hook */
  if (!NILP (Vrun_hooks))
    {
      Lisp_Object args[2];
      args[0] = intern ("delete-mystruct-hook");
      args[1] = mystruct;
      Frun_hook_with_args (2, args);
    }

  /* How can I make it void? */
  /* Fset (mystruct, Qunbound); */

  return Qnil;
}


/*
  LISP ACCESSORS
  An example of a getter is the function Fwindow_height(),
  which gets `height' in a window struct using the lisp
  function `window-height'.
  An example of a setter is the function Fset_window_hscroll(),
  which sets `hscroll' in a window struct using the lisp
  function `set-window-hscroll'.
*/

DEFUN ("mystruct-i", Fmystruct_i, Smystruct_i, 1, 1, 0,
  "Return the `i' member of MYSTRUCT.")
  (mystruct)
     Lisp_Object mystruct;
{
  if (NILP (mystruct))
    return Qnil;
  else
    return XMYSTRUCT (mystruct)->i;
}

DEFUN ("set-mystruct-i", Fset_mystruct_i, Sset_mystruct_i, 2, 2, 0,
  "Set the `i' member of MYSTRUCT to I.")
  (mystruct, i_obj)
     Lisp_Object mystruct, i_obj;
{
  MYSTRUCT_PTR m;
  int i;

  CHECK_MYSTRUCT(mystruct, 0);
  m = XMYSTRUCT (mystruct);

  CHECK_NUMBER (i_obj, 1);
  m->i = XINT (i_obj);
  return i_obj;
}



/*
  This is for the DEFUN()s, which make "primitive functions".
  Read `C-h i m Emacs Lisp Reference m GNU Emacs Internals`.
  Also, to compile it, go to the src directory. Put this file
  there called mystruct.c, add mystruct.o to `objs' in Makefile,
  and add a mystruct.o  target like this
    mystruct.o: mystruct.c $(config_h)
  then `make`. Run with ./emacs from the src directory.
*/

void syms_of_mysql ()
{
  Qmystructp = intern ("mystructp");
  staticpro (&Qmystructp);

  defsubr(&Screate_mystruct);
  defsubr(&Sdelete_mystruct);
  defsubr(&Smystruct_i);
  defsubr(&Sset_mystruct_i);
}




reply via email to

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