Emacs Module : Test 1
Since I've heard about Emacs' Dynamic Module feature, I've wanted to try it out. This article presents a small "hello world" with this feature.
This article could have been a gist.
#include "emacs-module.h" #include <string.h> int plugin_is_GPL_compatible; /* To test (progn (compile "cc -shared -o my-module.so my-module.c") (module-load (expand-file-name "./my-module.so")) (my-module/test1)) Inspired by: - http://diobla.info/blog-archive/modules-tut.html - https://phst.eu/emacs-modules - https://nullprogram.com/blog/2016/11/05/ - https://github.com/jkitchin/emacs-modules */ static emacs_value Fmy_print_message(emacs_env *env, ptrdiff_t nargs, emacs_value* args, void *data) { const char *str = "Hello from my module"; emacs_value string = env->make_string(env, str, strlen(str)); emacs_value fun = env->intern(env, "message"); emacs_value _args[] = { string }; env->funcall(env, fun, 1, _args ); return env->intern(env, "nil"); } /* Bind NAME to FUN. */ static void bind_function (emacs_env *env, const char *name, emacs_value Sfun) { /* Set the function cell of the symbol named NAME to SFUN using the 'fset' function. */ /* Convert the strings to symbols by interning them */ emacs_value Qfset = env->intern (env, "fset"); emacs_value Qsym = env->intern (env, name); /* Prepare the arguments array */ emacs_value args[] = { Qsym, Sfun }; /* Make the call (2 == nb of arguments) */ env->funcall (env, Qfset, 2, args); } /* Provide FEATURE to Emacs. */ static void provide (emacs_env *env, const char *feature) { /* call 'provide' with FEATURE converted to a symbol */ 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 *runtime) { int emacs_version; emacs_env *env = runtime->get_environment (runtime); if (env->size >= sizeof (struct emacs_env_26)) emacs_version = 26; /* Emacs 26 or later. */ else if (env->size >= sizeof (struct emacs_env_25)) emacs_version = 25; else return 2; /* Unknown or unsupported version. */ /* Print a message to say when the module is loaded. */ { emacs_value message = env->intern(env, "message"); const char hi[] = "Hello, world from my module!"; emacs_value string = env->make_string(env, hi, sizeof(hi) - 1); env->funcall(env, message, 1, &string); } /* create a lambda (returns an emacs_value) */ emacs_value fun = env->make_function (env, 0, /* min. number of arguments */ 0, /* max. number of arguments */ Fmy_print_message, /* actual function pointer */ "doc", /* docstring */ NULL /* user pointer of your choice (data param in Fmy_fun) */ ); bind_function(env, "my-module/test1", fun); provide(env, "my-module"); return 0; }
To test it, save the C code in a file my-module.c
and execute the following:
(progn (compile "cc -shared -o my-module.so my-module.c") (module-load (expand-file-name "./my-module.so")) (my-module/test1))
Inspired by: