[gnu.emacs] SUMMARY: Literal elisp symbols in a C function

mesard@bbn.com (Wayne Mesard) (08/23/89)

In article <44539@bbn.COM> I write:
[...]
>In C these constants are
>#define'ed in a header file, and in "normal" Lisp, I'd simply make them
>symbols in the keyword package.  But I'm not sure what to do in elisp.
[...]
>I will summarize email replies.

I got several good responses.  Thanks to all.

------------------
[[Carl Witty provides the C hacker's approach to the problem: the old
intialize-it-the-first-time-you-use-it trick.]]

From: Carl Witty <cwitty@csli.stanford.edu>

I don't know anything about the internals of Emacs, but in other
situations, with similar problems, I'd use something like:

{
  static Symbol Above = NULL, Below;

  if (Above == NULL) {
    Above = make-symbol("above");
    Below = make-symbol("below");
  }

  if (argument == Above) {
  }
}

You get the idea.

----------------------

[[Then there's the Lisp assumption that C is broken to begin with and it
would be easier to do the interface in Lisp and the guts in C.  True or
not, that's cheating:-]]

From: "Eric L. Raible" <raible@ew09.nas.nasa.gov>

(defvar *window-stack-mode* '((Above . 1) (Below . 2) ...))

(defun XConfigureWindow-lisp (window type)
  (XConfigureWindow-C window (cdr (assoc (type *window-stack-mode*)))))

and then do the switch in C.

----------------------
[[Both Stephen Gildea and Wolfgang Rupprecht pointed me towards the
Right(tm) solution.  What I had stupidly overlooked was the syms_of_*
functions that can be found at the bottom of nearly every src/*.c
file.]]

From: Stephen Gildea <gildea@BBN.COM>

You want to use symbols.  Although you cannot intern a symbol at
compile time, you can do it at dump time, which is just as good.  Look
in emacs.c just after the comment "Intern the names of all standard
functions and variables ..."

 < Stephen

------------------------
From: wolfgang@BBN.COM

This one is easy...

You can make elisp symbols from C fairly easily.  Check the bottom of
most emacs C files for examples.  (eg. data.c:syms_of_data())

Just make the required keyword symbols, and garbage protect them. Now
use them as keywords. Just compare their addresses to the addresses of
the passed symbols.  (I honestly haven't tried this, but I assume you
get the eval-ed lisp passed to your C routines.  I would think this
would be the lisp object, which should be a symbol pointer to one of
your keywords.)

-wolfgang

-------------------------

This is, in fact, what I wound up doing.

First I define new global variables:

    Lisp_Object Qabove, Qbelow, Qtop_if, Qbottom_if, Qopposite;


Then the function itself contains the fragment:

    if (!NULL (stack_mode)) {
	CHECK_SYMBOL(stack_mode, 4);
	mask |= CWStackMode;
	if (stack_mode == Qabove)
	    changes.stack_mode = Above;
	else if (stack_mode == Qbelow)
	    changes.stack_mode = Below; 
	[...]
	else {
	    error ("Illegal stack_mode keyword: %s", 
		   XSYMBOL (stack_mode)->name->data);

Then in syms_of_xfns(), defined at the bottom of x11fns.c, I add the
following lines:

  Qabove = intern("above");
  Qbelow = intern("below");
  [...]
  staticpro(&Qabove);
  staticpro(&Qbelow);
  [...]

Once again, I find myself happily impressed with Emacs' system design.


-- 
unsigned *Wayne_Mesard();    "Brain and brain!  What is brain?"
Mesard@BBN.COM               
BBN, Cambridge, MA                 -Kara, Leader of the Eymorgs