Skip to content

Instantly share code, notes, and snippets.

@namandixit
Last active August 24, 2025 09:46
Show Gist options
  • Save namandixit/ad99b7ea9c4a044ebd94bf7a263842e1 to your computer and use it in GitHub Desktop.
Save namandixit/ad99b7ea9c4a044ebd94bf7a263842e1 to your computer and use it in GitHub Desktop.
Embeddable Common Lisp

Instructions for using Embeddable Comon Lisp

This sets up ECL to be used for compile time C code spilicing.

Windows

To compile:

  1. Download tarball from from https://ecl.common-lisp.dev/
  2. Extract
  3. Read the instructions in INSTALL file. The ones that I followed were:
  4. Go to msvc
  5. Run nmake ECL_WIN64=1
  6. Run nmame install ECL_WIN64=1
  7. The compilation output is in the package directory. Add this directory to PATH

To use:

  1. Open the Native Tools Command Prompt from MSVC install and add ECL's package directory in PATH variable.

  2. Make a build directory and copy ecl.dll, ecl.lib and encodings from ECL's package directory to the build directory.

  3. Download the test.lisp, test.asd and test.c files from this gist.

  4. Run ecl to enter REPL, an run the following code:

    1. (ext:install-c-compiler)

    2. (require 'asdf)

    3. (push "./" asdf:*central-registry*)

    4. (asdf:make-build :test :type :static-library :move-here #P"./build/lisp" :init-name "LISP_init_test")

    5. (quit)

      This can all be done in one go using

      ecl -norc ^
          -eval "(ext:install-c-compiler)" ^
          -eval "(require 'asdf)" ^
          -eval "(push \"./\" asdf:*central-registry*)" ^
          -eval "(asdf:make-build :test :type :static-library :move-here #P\"./build/lisp\" :init-name \"LISP_init_test\")" ^
          -eval "(quit)"
      
  5. Run the following commands (change the include path to ECL's package directory):

    1. cl /MD /I ecl-24.5.10\msvc\package test.c /c /Fobuild\test.obj
    2. cl build\test.obj build\lisp\test.lib /Febuild\test.exe build\ecl.lib
  6. Run the executable by build\test

    >build\test
    0.46126956
    0.46126956
    0.4612695550331807d0
    
(defsystem "test"
:components ((:file "test")))
#include <stdio.h>
#include "ecl/ecl.h"
extern void LISP_init_test(cl_object cblock);
int main (int argc, char **argv) {
/* Initialize ECL */
cl_boot(argc, argv);
/* call the init function via ecl_init_module */
ecl_init_module(NULL, LISP_init_test);
cl_eval(c_string_to_object("(format t \"~a~%\" (sin (sin 0.5)))"));
cl_eval(c_string_to_object("(format t \"~a~%\" (sinsin-lisp 0.5))"));
cl_eval(c_string_to_object("(format t \"~a~%\" (sinsin-c 0.5))"));
ecl_terpri(ECL_T);
cl_shutdown();
return 0;
}
(defmacro gen-clines-with-sin ()
`(progn
;; Inject the C code into the generated C output
(ffi:clines "#include <math.h>")
(ffi:clines "double sinsin(double x) { return sin(sin(x)); }")
;; Define sinsin-c as a thin wrapper using a single expression (one-liner)
(defun sinsin-c (x)
(ffi:c-inline (x) (:double) :double
"sinsin(#0)"
:one-liner t))))
(gen-clines-with-sin)
;; Separate Lisp implementation of sinsin to check whether we can call it from C
(defun sinsin-lisp (x) (sin (sin x)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment