On 02/17/2015 09:46 AM, Aurélien Aptel wrote: > I'm with Eli on the versionning choice but it's just bike shedding at > this point. I'm worried about what happens during long Emacs development cycles. Say we're developing Emacs 26 and during its yearlong release cycle, we add to emacs_env a `make_foo' in month 3 and an `access_bar' hook in month 6. I want to make an distribute a module that uses `make_foo' if it's available. If we have some kind of explicit versioning enum, we'll probably have only one per Emacs release, so modules won't be able to detect that `foo' is available until we release Emacs 26. If we make the version date-based, we'll have a lot of different versions, and it'll be hard for a module author to figure out which constant they need to test against. A size field seems just right, since it automatically updates when and only when we add something to the struct. > Interning all the time seems tedious and probably (a bit?) slow but > moving the interning on Emacs side won't change the slow part. At > least on the module side you can do it once and reuse the result. Or > maybe you shouldn't if the user changes the binding in the meantime? I agree that interning all the time is tedious, but I don't intend module authors to use this interface directly. What I've described is just the narrow ABI-stable boundary between Emacs and modules; we can give module authors a richer "client" library, implemented in terms of the stable ABI, that itself doesn't need to ABI-stable (although we should try to make it source-compatible upwardly). I have a few ideas for making life easy for module authors. One idea is to make evaluating Lisp very easy. We can provide something like this: bool emacs_eval(emacs_env* env, const char* lisp, ...); Then module authors can write code like this: success = emacs_eval(env, "(put-text-property %v %v 'myproperty (myfunction))", value_min, value_max); Internally, we'd then call (using emacs_env::funcall) a function we'd define in Lisp in Emacs: (%module-eval "(put-text-property %v %v...)" ) That function would then transform the %v substitutions to expressions like (nth module-eval-arguments 0) (nth module-eval-arguments 1)) And then call (let ((module-eval-arguments args)) (eval expression-from-module)) This interface isn't the most efficient thing in the world, but it's hard to be more convenient, and it's good enough for code that isn't executed frequently.