Skip to content
forked from saikyun/clobits

Clojure ❤️ C — Use C inside Clojure, run on JVM + native

License

Notifications You must be signed in to change notification settings

epiccastle/clobits

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Clobits — Clojure ❤️ C

Use C inside Clojure, then run it on the JVM or compile a native binary.

Features

  • One source to rule them all — write code once, run it on both jvm and native binary
(ns clobits.examples.sdl.startup
  (:require [clobits.native-interop :refer [*native-image*]])
  (:gen-class))

(if *native-image*
  (do (println "In native image context")
      (require '[bindings.sdl_ni])
      (import '[bindings sdl]))
  (do (println "In polyglot context")
      (require '[bindings.sdl-ns :as sdl])))

(defn -main [& args]
  (sdl/init (sdl/get-sdl-init-video)))

For a more complete example, check out src/clobits/examples/sdl/startup.clj

Misc. features

  • Parse C function prototypes to Clojure maps
  • Generate .h/.c-files and Clojure namespaces based off of C function prototypes or using Clojure maps

Project status

This project is a work in progress. I wanted to share this mostly to add another example of how to use Clojure + C using GraalVM.

I'd be very happy if you tried to use it and have questions. If you have a specific C library you want to get working, let me know. Since the generated code can be reused, it'd be nice if we could host the bits required for various C libraries at clojars. :)

Known unknowns and possible solutions

  • Calling variadic C functions that do not have a va_args variation (see printf vs vprintf)
    • If the function has a va_args variant, I'd recommend just using that for now

If you know how to solve the problems below, please tell me how! :) Either through an issue, or @Saikyun on twitter.

Prerequisites

Tested on macos and linux.

Get the source

git clone https://github.com/Saikyun/clobits
cd clobits

Generate bindings (optional)

make clean bindings

ncurses Example

Displays hello for a second.

Run on JVM using Polyglot

make clean ncurses-poly

Compile and run a native binary using native-image

make clean ncurses-ni

SDL Example

Get libSDL2

You need libSDL2 on your path, and possibly added to "-Djava.library.path=<LIB_PATH_HERE>" under your OS profile in project.clj. I've put some defaults there, but I'm not sure they're universal.

Run on JVM using Polyglot

make clean sdl-poly

Compile and run a native binary using native-image

make clean sdl-ni

You should see a red square on a white background. Cmd+Q to exit on MacOS. You can also press the X.

Errors

If you don't run clean when switching between poly / ni targets you can get complaints about not finding clojure.core/seq?. I think this has to do with how leningen caches .class-files. Just run make clean ni / poly and you'll be fine.

The generated files

Running make clean bindings generates the folder src/bindings. This folder is included in the repo so that one can read the generated source when looking at github. As soon as you start using this library, you will overwrite these files. They should not be modified by hand.

In src/bindings you'll find:

sdl.c and sdl.h -- generated c code

These are necessary for polyglot to be able to call native libs.

sdl_ni.clj

Clojure code that generates classes and interfaces to be with native-image

sdl_ns.clj

Clojure namespace that is used with polyglot.

How to put it all together

Look at src/clobits/examples/startup.clj to see how you can use the same code for both polyglot and native-image.

Thanks

License

Copyright © 2020 Jona Ekenberg

Distributed under the EPL License. See LICENSE.

This project contains code from:

  • Clojure, which is licensed under the same EPL License.
  • clj-kondo, which is licensed under the same EPL License.

About

Clojure ❤️ C — Use C inside Clojure, run on JVM + native

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Clojure 92.7%
  • C 4.4%
  • Shell 1.4%
  • Makefile 1.1%
  • C++ 0.4%