Skip to content

FFI Design Discussions

Michael Grünewald edited this page Oct 28, 2017 · 3 revisions

I open this page to discuss the design of the FFI system.

Current situation

A primitive function (oget <object> <property1> <property2> ...) is exposed. A base *root* variable designates the main object (which is established by the runtime).

On NodeJS it doesn't work properly though as there are some variables that are in the module scope but are not in global, but I think those are just a few and the NodeJS runtime can provide them as special cases.

On top of that, a #j macrocharacter is implemented so (#j:console:log "test") is read as ((oget *root* "console" "log") "test") which basically does the right thing.

Problem 1: accessing properties of your own CL variables

#j: always work with the root object, which make it inconvenient to work with your own CL variables. You can't do

(defvar canvas (#j:document:querySelector "#canvas"))
(#j:canvas:getContext "2d")  ;  would be read as ((oget *root* "canvas" "getContext") "2d")

Ideas

  • Make #j:a:b:c expand to (oget a "b" "c"). Then you can use *root* if you need to or it could be provided by the shortcut #j::a:b (oget root "a" "b"). I don't like the first argument being different but not the syntax. Perhaps its hould be (#j/a:b:c) instead??

Problem 2: Constructing new objects

Problem 3: Conversion between Lisp and JS values

oget converts between JS and Lisp values automatically. Sometimes we do not want this, how should we disable this? Another variant of #j:: or #j/? A special variable *convert-ffi-values*? My concern with the latter is that special variables could not play well with async code.

Clone this wiki locally