Common Lisp and CXX interoperation with JIT

Overview

CL-CXX-JIT - Common Lisp C++ JIT for exposing C++ functions

This library provides an interface to C++ from lisp. It compiles C++ code, then loads it into lisp. It was inspired by RCRL and the older project CL-CXX.

API

(from '("list of string headers") 'import "normal string is inserted as it is" '("function/function-pointer/mem-fun-pointer/lambda" . "name-used-in-lisp"))

Examples

SDL2 Example

sdl2.gif

(ql:quickload :cxx-jit)
(setf cxx-jit:*cxx-compiler-link-libs* "-lGL -lSDL2 -lSDL2main")

(cxx-jit:from '(
                "<SDL2/SDL.h>")
              'import
              '("[](){return SDL_Init(SDL_Init(SDL_INIT_VIDEO));}" . "init")
              '("SDL_CreateWindow" . "create-window")
              '("SDL_CreateRenderer" . "create-renderer")
              '("SDL_SetRenderDrawColor" . "set-color")
              '("SDL_DestroyWindow" . "destroy-window")
              '("SDL_RenderClear" . "clear-renderer")
              '("SDL_RenderPresent" . "renderer-render")
              '("SDL_Quit" . "sdl-quit"))

(init)
(setf wind (create-window "create-window" 0 0 600 700 0))
(setf rend (create-renderer wind -1 0))
(loop for x to (* 255 3)
      for r = (if (> x 255) 255 x)
      for g = (if (> x 255) (if (> x (* 2 255)) 255 (rem x 256)) 0)
      for b = (if (> x (* 2 255)) (rem x 256) 0)
      do
         (print x)
         (set-color rend r g b 255)
         (clear-renderer rend)
         (renderer-render rend)
         (sleep 0.01))

(destroy-window wind)
(sdl-quit)

Basic Example

Start with (ql:quickload :cxx-jit) (in-package cxx-jit)

(from '("<string>") 'import '("[](std::string x){return \"Hi, \"+x;}" . "hi"))
(hi "there!")

(from '("<cmath>") 'import '("static_cast<double(*)(double)>(std::sin)" . "cpp-sin"))
(cpp-sin 0d0)
(cpp-sin pi)
(cpp-sin (/ pi 2))

(from nil 'import "struct C{ auto hi(){return \"Hello, World\\n\";} auto bye(){return \"Bye\";} };" '("&C::bye" . "bye") '("&C::hi" . "hi") '("[](){static C x; return x;}" . "cc"))
(cc)
(hi *)
(bye **)
  ;;; structure  definition could be written in a header file then be used as the following:
(from '("c.hpp") 'import '("&C::bye" . "bye") '("&C::hi" . "hi") '("[](){static C x; return x;}" . "cc"))

Eigen Library Example

Start with (ql:quickload :cxx-jit) (in-package cxx-jit)

     (from '("<Eigen/Core>" "<Eigen/Core>") 'import '("[](Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>,Eigen::Matrix<double, 3, 3>> x){std::stringstream s;
         s << x;
         return s.str();}" . "print-matrix"))

    (from '("<Eigen/Core>" "<Eigen/Core>") 'import '("static_cast<const Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>,Eigen::Matrix<double, 3, 3>> (*)()> (&Eigen::Matrix3d::Identity)" . "identity-matrix"))

(print-matrix (identity-matrix))

Prerequisites

  • common lisp supporting CFFI
  • working C++17 compiler
  • the following variables should be set according to OS and compiler used
variable default value
*cxx-compiler-executable-path* /usr/bin/g++
*cxx-compiler-flags* -std=c++17 -Wall -Wextra -I/usr/include/eigen3
*cxx-compiler-working-directory* /tmp/” #\/ ‘/’ should be the last character
+cxx-compiler-lib-name+ plugin
+cxx-compiler-wrap-cxx-path+ shouldn’t be changed ”path to wrap-cxx.cpp
*cxx-compiler-internal-flags* -shared -fPIC -Wl,--no-undefined -Wl,--no-allow-shlib-undefined
for g++ and for clang++ ”-shared -fPIC -undefined error -flat_namespace
*cxx-compiler-link-libs* -lmath” these flags are added after ”-o output” to link correctly

Installation

Clone into home/common-lisp directory. Then (ql:quickload :cxx-jit-test)

Supported Types

C++ type Lisp cffi type
fundamental same
string :string
class :pointer
std::is_function :pointer
other not implemented!

Under The Hood

  • function/lambda/member_function/function_pointer is wrapped into a dummy lambda class to have a unique template specialization.
    Import([&]() { return __VA_ARGS__; });
        
  • Import function calls DecayThenResolve with function pointer as the template specialization so thunk pointer is omitted and we only return the direct function pointer which will be used from lisp side.
  • InvocableTypeName returns a vector contains: [return type, class type for class function member, args]. It resolves C++ types as follows:
    • Fundamental types and pointers are passed directly
    • String is converted to char* with new[] operator, should be cleared with ClCxxDeleteObject(ptr, true)
    • Class/std::is_function is converted to void* with new[] operator, should be cleared with ClCxxDeleteObject(ptr, false)
    • rest report an issue for other cases
  • Meta data for each function defined is passed through a lisp callback with this data:
    typedef struct {
      // could be void*
      void (*thunk_ptr)();
      bool method_p;
      const char **type;  // memory handled in C++
      std::uint8_t type_size;
    } MetaData;
        

NOTE

Tested on:

  • SBCL 2.0.1 on debian

Todo List

Use trivial-garbage with ClCxxDeleteObject

Add non-polling from

Test functions

Benchmark

Better class interface

Copyright

Copyright (c) 2021 Islam Omar ([email protected])

License

Licensed under the MIT License.

You might also like...
aLisp - a custom Lisp in C

aLisp aims to become a hackable, embeddable, reasonably fast interpreted custom Lisp implemented in portable C.

CAAR is an attempt at writing a modern Lisp machine.
CAAR is an attempt at writing a modern Lisp machine.

CAAR - The modern lisp machine CAAR is an attempt at writing a modern Lisp machine. The goal of this project is to be able to run a somewhat functiona

A multiplatform C++ library for common and basic system functionalities.

axl.cm A multiplatform C++ library for common and basic system functionalities. Platforms Linux Windows C++ standard minimum: C++98 target: C++11 maxi

This package contains the common algorithms in robotic arm, and I have developed it based on universal robot. It will be continuously updateing.
This package contains the common algorithms in robotic arm, and I have developed it based on universal robot. It will be continuously updateing.

Robotic_Arm_Algorithms It contains the common algorithms in robotic arm, and will be recording the development as soon as I have completed the any one

Common Sensor API for the BMA2 family of sensors

BMA2 Sensor API Sensor overview The BMA2 is a triaxial, low-g acceleration sensor with digital output. An ASIC in the sensor converts the output of a

Common Device Source For Xiaomi Redmi Note 5 Pro (whyred)

The Redmi Note 5 Pro (codenamed "whyred") are high-end mid-range smartphones from Xiaomi announced and released in February 2018. Device specification

A repository that includes common helper functions for writing applications in the DPDK. I will be using this for my future projects in the DPDK.

The DPDK Common (WIP) Description This project includes helpful functions and global variables for developing applications using the DPDK. I am using

A C library for runtime-flippable feature flags on Linux/x86-64, with negligible overhead in the common case

Biased runtime-flippable flags, with cross-modifying code The dynamic_flag library is a two-file "C" library that offers efficient biased conditionals

How do I submit patches to Android Common Kernels

How do I submit patches to Android Common Kernels BEST: Make all of your changes to upstream Linux. If appropriate, backport to the stable releases. T

Comments
  • Multiple working directory

    Multiple working directory

    Hello, I am curious whether its possible to setup multiple working directory instead of just "/tmp/", because there are multiple hpp header files spread across the system. Or the only option at the moment is collecting them and all put in /tmp/ directory?

    question 
    opened by tcyuan373 10
  • define types in an variable or parameter

    define types in an variable or parameter

    Hi, I find this package very handy, but I got an issue with unregistered types.

    Currently all return types is registered in the cffi-type function in the cxx-jit.lisp. But whenever it faces an unregistered type, it will say something like No Known conversion for type "long unsigned int". default to pointer. Can you move the type registration into an variable, so users can extend it?

    enhancement 
    opened by leosongwei 4
Owner
Islam Omar
Islam Omar
Common Lisp editor/IDE with high expansibility

Lem is the editor/IDE well-tuned for Common Lisp. After installing lem, you can start developing in Common Lisp at once. You can skip over writing tid

null 1.3k Oct 2, 2022
C language simulation CXX template library

lib.xtl This is the implementation of a C language imitation cxx template library Explain This library simulates some operations in STL. Simulation ve

libxanadu 1 Jan 8, 2022
BSCXX (for BootStrap CXX project) is a C++ package manager.

bscxx bscxx (for bootstrap CXX project) is a very light utility software, written in C++ 17, to help you starting quickly a new C++ project using cmak

Victor Gallet 1 Sep 21, 2019
Mirror of MRuby JIT

What is mruby mruby is the lightweight implementation of the Ruby language complying to (part of) the ISO standard. Its syntax is Ruby 1.9 compatible.

The Ruby Compiler Survey 2 Nov 18, 2021
Simple, fast, JIT-compiled scripting language for game engines.

Aftel Aftel (acronym for «A Far Too Easy Language») is a programming language, primarily intended to serve as an embeddable scripting language for gam

Rosie 17 May 20, 2022
Lua + libUV + jIT = pure awesomesauce

Luvit 2.0 - Node.JS for the Lua Inventor Welcome to the source code for Luvit 2.0. This repo contains the luvit/luvit metapackage and all luvit/* pack

Luvit Community 3.5k Sep 29, 2022
Per function, Lua JIT using LLVM C++ toolchain

Lua Low Level Brief This is an alternative Lua (5.3.2) implementation that aims to archive better performance by generating native code with the help

Gabriel de Quadros Ligneul 10 Sep 4, 2021
A C++ expression -> x64 JIT

NativeJIT NativeJIT is an open-source cross-platform library for high-performance just-in-time compilation of expressions involving C data structures.

null 1.1k Sep 29, 2022
A light lisp written in C++

wisp A light lisp written in C++ Why write a lisp? Lisp is one of those niche, beautiful languages that people only really use to either Write a lisp

adam mcdaniel 163 Sep 28, 2022
tree-sitter grammar for emacs lisp

Tree-sitter Grammar for Emacs Lisp A simple tree-sitter grammar for elisp. Syntax supported: Atoms (integers, floats, strings, characters, symbols) Li

Wilfred Hughes 21 Sep 12, 2022