Skip to content

Commit

Permalink
add modules using Daniel Colascione ideas
Browse files Browse the repository at this point in the history
See [1] for Daniel's proposal.

* src/module.c: new file
* src/emacs_module.h: module API
* src/Makefile.in: hardcode libltdl link flag and module.c compilation
* modules/basic/basic.c: sample module
* modules/basic/Makefile: module Makefile for linux

1: https://lists.gnu.org/archive/html/emacs-devel/2015-02/msg00960.html
  • Loading branch information
aaptel committed Feb 28, 2015
1 parent e605af8 commit 278f26a
Show file tree
Hide file tree
Showing 7 changed files with 418 additions and 2 deletions.
15 changes: 15 additions & 0 deletions modules/basic/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ROOT = ../..

CFLAGS =
LDFLAGS =

all: basic.so basic.doc

%.so: %.o
gcc -shared $(LDFLAGS) -o $@ $<

%.o: %.c
gcc -ggdb3 -Wall -I$(ROOT)/src $(CFLAGS) -fPIC -c $<

%.doc: %.c
$(ROOT)/lib-src/make-docfile $< > $@
64 changes: 64 additions & 0 deletions modules/basic/basic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
basic.c - sample module
This module provides a simple `basic-sum' function.
I've used the following prefixes throughout the code:
- Sfoo: subr (function wraper)
- Qfoo: symbol value
- Ffoo: function value
*/

#include <emacs_module.h>

int plugin_is_GPL_compatible;

/* C function we want to expose to emacs */
static int64_t sum (int64_t a, int64_t b)
{
return a + b;
}

/* Proper module subr that wraps the C function */
static emacs_value Fsum (emacs_env *env, int nargs, emacs_value args[])
{
int64_t a = env->fixnum_to_int (env, args[0]);
int64_t b = env->fixnum_to_int (env, args[1]);

int64_t r = sum(a, b);

return env->make_fixnum (env, r);
}

/* Binds NAME to FUN */
static void bind_function (emacs_env *env, const char *name, emacs_value Ffun)
{
emacs_value Qfset = env->intern (env, "fset");
emacs_value Qsym = env->intern (env, name);
emacs_value args[] = { Qsym, Ffun };

env->funcall (env, Qfset, 2, args);
}

/* Provide FEATURE to Emacs */
static void provide (emacs_env *env, const char *feature)
{
emacs_value Qfeat = env->intern (env, feature);
emacs_value Qprovide = env->intern (env, "provide");
emacs_value args[] = { Qfeat };

env->funcall (env, Qprovide, 1, args);
}

int emacs_module_init (struct emacs_runtime *ert)
{
emacs_env *env = ert->get_environment (ert);
emacs_value Ssum = env->make_function (env, 2, 2, Fsum);

bind_function (env, "basic-sum", Ssum);
provide (env, "basic");

return 0;
}
4 changes: 2 additions & 2 deletions src/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
minibuf.o fileio.o dired.o \
cmds.o casetab.o casefiddle.o indent.o search.o regex.o undo.o \
alloc.o data.o doc.o editfns.o callint.o \
eval.o floatfns.o fns.o font.o print.o lread.o \
eval.o floatfns.o fns.o font.o print.o lread.o module.o \
syntax.o $(UNEXEC_OBJ) bytecode.o \
process.o gnutls.o callproc.o \
region-cache.o sound.o atimer.o \
Expand Down Expand Up @@ -427,7 +427,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
$(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \
$(GFILENOTIFY_LIBS) $(LIB_MATH) $(LIBZ)
$(GFILENOTIFY_LIBS) $(LIB_MATH) $(LIBZ) -lltdl

all: emacs$(EXEEXT) $(OTHER_FILES)
.PHONY: all
Expand Down
3 changes: 3 additions & 0 deletions src/emacs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
syms_of_terminal ();
syms_of_term ();
syms_of_undo ();

syms_of_module ();

#ifdef HAVE_SOUND
syms_of_sound ();
#endif
Expand Down
124 changes: 124 additions & 0 deletions src/emacs_module.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
emacs_module.h - Module API
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef EMACS_MODULE_H
#define EMACS_MODULE_H

#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

/* Current environement */
typedef struct emacs_env_25 emacs_env;
typedef void* emacs_value;

/* Struct passed to a module init function (emacs_module_init) */
struct emacs_runtime {
size_t size;
emacs_env* (*get_environment)(struct emacs_runtime *ert);
};


/* Function prototype for the module init function */
typedef int (*emacs_init_function)(struct emacs_runtime *ert);

/* Function prototype for the module Lisp functions */
typedef emacs_value (*emacs_subr)(emacs_env *env,
int nargs,
emacs_value args[]);
struct emacs_env_25 {
/*
* Structure size (for version checking)
*/

size_t size;

/*
* Memory management
*/

emacs_value (*make_global_reference)(emacs_env *env,
emacs_value any_reference);

void (*free_global_reference)(emacs_env *env,
emacs_value global_reference);

/*
* Error handling
*/

bool (*error_check)(emacs_env *env);

void (*clear_error)(emacs_env *env);

bool (*get_error)(emacs_env *env,
emacs_value *error_symbol_out,
emacs_value *error_data_out);

void (*signal_error)(emacs_env *env,
emacs_value error_symbol,
emacs_value error_data);

/*
* Function registration
*/

emacs_value (*make_function)(emacs_env *env,
int min_arity,
int max_arity,
emacs_subr function);

emacs_value (*funcall)(emacs_env *env,
emacs_value function,
int nargs,
emacs_value args[]);

emacs_value (*intern)(emacs_env *env,
const char *symbol_name);

/*
* Type conversion
*/

emacs_value (*type_of)(emacs_env *env,
emacs_value value);

int64_t (*fixnum_to_int)(emacs_env *env,
emacs_value value);

emacs_value (*make_fixnum)(emacs_env *env,
int64_t value);

double (*float_to_c_double)(emacs_env *env,
emacs_value value);

emacs_value (*make_float)(emacs_env *env,
double value);

bool (*copy_string_contents)(emacs_env *env,
emacs_value value,
char *buffer,
size_t* length_inout);

emacs_value (*make_string)(emacs_env *env,
const char *contents);
};

#endif /* EMACS_MODULE_H */
2 changes: 2 additions & 0 deletions src/lisp.h
Original file line number Diff line number Diff line change
Expand Up @@ -4021,6 +4021,8 @@ Lisp_Object backtrace_top_function (void);
extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol);
extern bool let_shadows_global_binding_p (Lisp_Object symbol);

/* Defined in module.c. */
void syms_of_module (void);

/* Defined in editfns.c. */
extern void insert1 (Lisp_Object);
Expand Down
Loading

0 comments on commit 278f26a

Please sign in to comment.