[Top][All Lists]
[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);
}
- studying emacs internals,
Scott Lanning <=