62 lines
2.0 KiB
Markdown
62 lines
2.0 KiB
Markdown
# Haskell Interop Demo
|
|
|
|
This directory contains a small Haskell project for the repository's Rust/Haskell integration work.
|
|
|
|
The project demonstrates both directions:
|
|
|
|
- Haskell calling into Rust through a C ABI exposed by the Rust crate.
|
|
- Rust calling back into Haskell through a Cabal `foreign-library`, with explicit GHC RTS initialization.
|
|
|
|
## Layout
|
|
|
|
- `src/Interop/Shared.hs` - pure shared logic plus the C-compatible struct layout used at the boundary.
|
|
- `src/Interop/Exports.hs` - Haskell functions exported to C for Rust to call.
|
|
- `app/RustClient.hs` - Haskell imports for the Rust C ABI.
|
|
- `app/Main.hs` - Haskell executable that demonstrates the Haskell -> Rust path.
|
|
- `test/Spec.hs` - small pure tests that avoid crossing the FFI boundary.
|
|
|
|
The code keeps the FFI surface small on purpose. The boundary uses:
|
|
|
|
- integers
|
|
- a fixed C-shaped struct
|
|
- owned C strings with an explicit free function on each side
|
|
|
|
That is enough to demonstrate the main challenges without pulling in code generation or large bindings.
|
|
|
|
## Build And Run
|
|
|
|
From the repository root:
|
|
|
|
```sh
|
|
make haskell-build
|
|
```
|
|
|
|
Run the Haskell executable that calls Rust:
|
|
|
|
```sh
|
|
make haskell-run
|
|
```
|
|
|
|
Run the Rust executable that calls the Haskell foreign library:
|
|
|
|
```sh
|
|
make rust-calls-haskell
|
|
```
|
|
|
|
You can also run the commands manually:
|
|
|
|
```sh
|
|
cargo build --lib
|
|
cabal build --project-file=haskell/cabal.project all
|
|
cabal run --project-file=haskell/cabal.project haskell-calls-rust -- Ada 7 5
|
|
cargo run -- rust-calls-haskell Ada 7 5
|
|
```
|
|
|
|
## What This Demonstrates
|
|
|
|
- The boundary must stay C-shaped. Rich Rust and Haskell types do not cross directly.
|
|
- Strings need explicit ownership rules. Each side exports its own free function.
|
|
- Struct layout must be mirrored carefully on both sides.
|
|
- Rust calling Haskell is the harder direction because it must initialize and shut down the GHC runtime correctly.
|
|
- Build order is part of the design. Haskell links against the Rust static library, and Rust loads the Haskell foreign library after Cabal builds it.
|