Next: , Previous: , Up: Rules When Writing New C Code   [Contents][Index]


8.5 Adding Global Lisp Variables

Global variables whose names begin with ‘Q’ are constants whose value is a symbol of a particular name. The name of the variable should be derived from the name of the symbol using the same rules as for Lisp primitives. These variables are initialized using a call to defsymbol() in the syms_of_*() function. (This call interns a symbol, sets the C variable to the resulting Lisp object, and calls staticpro() on the C variable to tell the garbage-collection mechanism about this variable. What staticpro() does is add a pointer to the variable to a large global array; when garbage-collection happens, all pointers listed in the array are used as starting points for marking Lisp objects. This is important because it’s quite possible that the only current reference to the object is the C variable. In the case of symbols, the staticpro() doesn’t matter all that much because the symbol is contained in obarray, which is itself staticpro()ed. However, it’s possible that a naughty user could do something like uninterning the symbol out of obarray or even setting obarray to a different value [although this is likely to make SXEmacs crash!].)

Please note: It is potentially deadly if you declare a ‘Q...’ variable in two different modules. The two calls to defsymbol() are no problem, but some linkers will complain about multiply-defined symbols. The most insidious aspect of this is that often the link will succeed anyway, but then the resulting executable will sometimes crash in obscure ways during certain operations!

To avoid this problem, declare any symbols with common names (such as text) that are not obviously associated with this particular module in the file general-slots.h. The “-slots” suffix indicates that this is a file that is included multiple times in general.c. Redefinition of preprocessor macros allows the effects to be different in each context, so this is actually more convenient and less error-prone than doing it in your module.

Global variables whose names begin with ‘V’ are variables that contain Lisp objects. The convention here is that all global variables of type Lisp_Object begin with ‘V’, and all others don’t (including integer and boolean variables that have Lisp equivalents). Most of the time, these variables have equivalents in Lisp, but some don’t. Those that do are declared this way by a call to DEFVAR_LISP() in the vars_of_*() initializer for the module. What this does is create a special symbol-value-forward Lisp object that contains a pointer to the C variable, intern a symbol whose name is as specified in the call to DEFVAR_LISP(), and set its value to the symbol-value-forward Lisp object; it also calls staticpro() on the C variable to tell the garbage-collection mechanism about the variable. When eval (or actually symbol-value) encounters this special object in the process of retrieving a variable’s value, it follows the indirection to the C variable and gets its value. setq does similar things so that the C variable gets changed.

Whether or not you DEFVAR_LISP() a variable, you need to initialize it in the vars_of_*() function; otherwise it will end up as all zeroes, which is the integer 0 (not nil), and this is probably not what you want. Also, if the variable is not DEFVAR_LISP()ed, you must call staticpro() on the C variable in the vars_of_*() function. Otherwise, the garbage-collection mechanism won’t know that the object in this variable is in use, and will happily collect it and reuse its storage for another Lisp object, and you will be the one who’s unhappy when you can’t figure out how your variable got overwritten.


Next: , Previous: , Up: Rules When Writing New C Code   [Contents][Index]