Skip to content

Blog post about linking C code #96

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions blog/2024-09-25-js-link-c.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
slug: 2024-09-25-ghc-update
title: "Linking C code with GHC's JavaScript backend"
authors: [sylvain]
tags: [ghc,javascript]
---

Since GHC 9.10 it is possible to build and to link C code with Haskell code
compiled with the JavaScript backend. In this post we show to do it, using the
well-known SQLite database as an example.

<!-- truncate -->

Using JavaScript code produced from C code from JavaScript code produced
from Haskell code is [documented in GHC's users
guide](https://downloads.haskell.org/ghc/latest/docs/users_guide/javascript.html#linking-with-c-sources),
however it's probably simpler to understand with examples.
We'll start with a simple Hello World example and then directly leap to an
example using the SQLite database.

TODO: motivation. Why would we want to do that? Avoid reimplementing in Haskell.
Performance (need example + benchmark). Maybe a graphics C lib?

## Hello World

TODO

## SQLite

The SQLite database is released as a single C file. To use it from Haskell, we
can use the [direct-sqlite
package](https://hackage.haskell.org/package/direct-sqlite) which embeds this C
file and provides Haskell bindings for it.

Since GHC 9.10, if the JavaScript backend on GHC is used, by default the C files
are compiled to WebAssembly (using the [Emscripten](https://emscripten.org/)
compiler) and embedded into the produced JavaScript file. (You can disable this
behavior by passing the `-ddisable-js-c-sources` flag to GHC.)

The generated code can't be directly called into from Haskell. We need to write
some JavaScript code to call into the WebAssembly code, passing arguments into
the WebAssembly heap as needed. This is no as difficult as it should, especially
thanks to JavaScript helper functions provided by GHC's JavaScript RTS.

## Building the project

Note that we need to use at least GHC 9.10.2 for this to work as it contains a
fix for [#25288](https://gitlab.haskell.org/ghc/ghc/-/issues/25288).

FIXME: checkout branch in fork instead? https://github.com/hsyl20/direct-sqlite/tree/hsyl20/js

```bash
> git clone https://github.com/IreneKnapp/direct-sqlite -- FIXME: checkout MR
> cd direct-sqlite
> cabal build . -w /path/to/javascript-unknown-ghcjs-ghc --with-ghc-pkg=/path/to/javascript-unknown-ghcjs-ghc-pkg
> cabal test . -w /path/to/javascript-unknown-ghcjs-ghc --with-ghc-pkg=/path/to/javascript-unknown-ghcjs-ghc-pkg
Running 1 test suites...
Test suite test: RUNNING...
Cases: 25 Tried: 25 Errors: 0 Failures: 0
Cases: 1 Tried: 1 Errors: 0 Failures: 0
Cases: 26 Tried: 26 Errors: 0 Failures: 0
Cases: 1 Tried: 1 Errors: 0 Failures: 0
Test suite test: PASS
```