Firstly, Elisp is an interpreted language, and this has serious speed implications. Like all other interpreted languages, Elisp is often suitable only for certain types of application or extension. So although Elisp is a general purpose language, and very high level, there are times when it is desirable to descend to a lower level compiled language for speed purposes.
Secondly, Elisp (or Lisp in general) is not a very common language any more, except for certain circles in the computer industry. C is a far more commonly known language, and because it is compiled, more suited to a wider range of applications, especially those that require low level access to a system or need to be as quick as possible.
Having the ability to load such modules during run-time into GNU Emacs would be very useful. This topic has been discussed on GNU Emacs mailing lists several times. Unfortunately, RMS does not want this feature accepted into GNU Emacs. If you want to read up on this topic, I recommend Richards reply in a thread which started with this mail.
XEmacs modules are configured into and installed with XEmacs by default on all systems that support loading of shared objects. From a users perspective, the internals of XEmacs modules are irrelevant. All a user will ever need to know about shared objects is the name of the shared object when they want to load a given module. From a developers perspective though, a lot more is provided.
For more details, read the XEmacs 21.5 emodules documentation.
To: Mario Lang <mlang@delysid.org> Subject: Re: Special object types when writing emodules? From: Jerry James <james@xemacs.org> Date: Mon, 04 Aug 2003 13:19:47 -0500 Message-ID: <psadapffp8.fsf@diannao.ittc.ku.edu> User-Agent: Gnus/5.1002 (Gnus v5.10.2) XEmacs/21.4 (Rational FORTRAN, linux) Hi Mario, Mario Lang <mlang@delysid.org>, on Fri, 01 Aug 2003 at 12:32:51 +0200 you wrote: > I got your e-mail from Stephen J. Turnbull, he indicated to me > that you are knowledgeable regarding the emodule system > of xemacs21. I am trying to write a module which > provides bindings to GNOME AT-SPI. A long story short: > This binding has as primary data type a so-called object, which > is represented by a pointer. For the bindings being really useful, > I'd need to be able to encapsulate this pinter in a new > Emacs data type which can: > 1. Set a special print representation such that some information about > the object could be printed for convenience. Something like: > #<Accessible 0xsomeaddr name="objects-name" role="objects-role"> > > 2. Set a free function which would unreference the pointer > when gc decides to free the object in Lisp. > > Is such a thing possible using emodules. If so, could you give > me some pointers as to where find information on how to achieve > this? Yes, it is possible. You can find examples of this kind of thing in the LDAP and PostgreSQL modules that come with the XEmacs sources, as well as my own ViaVoice module: <URL:http://www.ittc.ku.edu/~james/xemacs/viavoice.html> The canonical source of information for modules is the emodules info file that comes with XEmacs. Here's a brief rundown on how to do what you want, though: 1) Make a header file that describes your type. In there, do something along these lines: struct gnome_at_spi { struct lcrecord_header header; void *ptr; /* Or whatever type this pointer actually is */ }; DECLARE_EXTERNAL_LRECORD (gnome_at_spi_, struct gnome_at_spi); #define XGNOME_AT_SPI(x) XRECORD (x, gnome_at_spi, struct gnome_at_spi) #define XSETGNOME_AT_SPI(x, p) XSETRECORD (x, p, gnome_at_spi) #define GNOME_AT_SPIP(x) RECORDP (x, gnome_at_spi) #define CHECK_GNOME_AT_SPI(x) CHECK_RECORD (x, gnome_at_spi) #define CONCHECK_GNOME_AT_SPI(x) CONCHECK_RECORD (x, gnome_at_spi) #define XREALGNOME_AT_SPI(x) XGNOME_AT_SPI(x)->ptr extern Lisp_Object make_gnome_at_spi (void * /* or whatever it is */); 2) Then in your .c file that contains the actual implementation, do something like this: Lisp_Object Qgnome_at_spip; /* DEFINE_EXTERNAL should really do this */ Lisp_Object make_gnome_at_spi (void *ptr) { Lisp_Object the_gnome_at_spi; struct gnome_at_spi *gnome_thing = alloc_lcrecord_type(struct gnome_at_spi, &lrecord_gnome_at_spi); gnome_thing->ptr = ptr; XSETGNOME_AT_SPI (the_gnome_at_spi, gnome_thing); return the_gnome_at_spi; } void finalize_gnome_at_spi (void *header, int for_disksave) { struct gnome_at_spi *gnome_thing = (struct gnome_at_spi *)header; if (!for_disksave) call_my_gnome_dereferencing_function (gnome_thing); } void print_gnome_at_spi (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) { write_c_string ("#<gnome-at-spi>", printcharfun); } DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION ("gnome-at-spi", gnome_at_spi, 0, 0, print_gnome_at_spi, finalize_gnome_at_spi, 0, 0, 0, struct gnome_at_spi); void syms_of_gnome_at_spi () { INIT_EXTERNAL_LRECORD_IMPLEMENTATION (gnome_at_spi); } Let me know if you need any more information. Regards, -- Jerry James Email: james@ittc.ku.edu -or- jamesj@acm.org WWW: http://www.ittc.ku.edu/~james/