Bridge the gap between Haskell and Rust

Overview

Curryrs

Curryrs (a play on the name of Haskell Curry, rs for Rust libraries, and it's pronunciation couriers) is a library for providing easy to use bindings between Rust and Haskell Code. Given the type safety inherent in both languages Curryrs seeks to bridge the gap between the two languages by providing an interface between the two that makes writing FFI code a relatively painless experience.

This library has only been tested with GHC 8.0.1 and Rust Stable. To run the test suite you'll need gcc.

Project Status

This library used to not work due to some linking issues. It's not working still right now in it's current state but a fix is on the way see here for more details!

Installation

In your Rust project in Cargo.toml:

[dependencies]
curryrs = "^0.2.0"

In your Haskell project in it's cabal file:

build-depends: curryrs >= 0.2.0 < 0.3.0

How to use Curryrs

Each library contains a module for the FFI types and one for conversion to and from types that need extra work to do so. Right now this conversion module only affects the Boolean type, however work in the future of this module will likely include structs and other more complicated data structures.

Rust in Haskell

If you want to create functions that export to Haskell from Rust do the following:

#[macro_use]
extern crate curryrs;

use curryrs::types::*;

// Place each function you want exported into the safe_ffi! macro and it will
// export each one and place the pub extern for you!
safe_ffi! (

	fn double(x: I32) -> I32 {
		2 * x
	}

	fn square(x: U64) -> U64 {
		x * x
	}

	fn cube(x: I64) -> I64 {
		x * x * x
	}

);

Currently this macro doesn't work if unsafe is put in as part of the fn header. There are two macros: safe_ffi! and unsafe_ffi!. While they are both the same for now when a binary is created to help auto generate the bindings it will create unsafe or safe imports to Haskell depending on which macros the functions are in. The recommended use case is safe_ffi! for most of what you'll need.

Then in your Haskell program:

import Curryrs.Types

foreign import ccall "double" double :: I64 -> I64
foreign import ccall "square" square :: I64 -> I64
foreign import ccall "cube" cube :: I64 -> I64

quadruple :: I64 -> I64
quadruple x = double $ double x

fourthPower :: I64 -> I64
fourthPower x = square $ square x

ninthPower :: I64 -> I64
ninthPower x = cube $ cube x

Haskell in Rust

To run your Haskell code in Rust do the following steps:

First write and export the code you want for Haskell and use the Curryrs.Types module to have FFI compatible types.

import Curryrs.Types

foreign export ccall fourth :: I64 -> I64
foreign export ccall fifth :: I64 -> I64
foreign export ccall sixth :: I64 -> I64

fourth :: I64 -> I64
fourth x = x * x * x * x

fifth :: I64 -> I64
fithh x = x * x * x * x * x

sixth :: I64 -> I64
sixth x = x * x * x * x * x * x

In your cabal file add the following lines:

other-extensions: ForeignFunctionInterface

-- It should end with .so if you're on Linux, .dylib for Mac, and
-- .dll for Windows
ghc-options: -dynamic -fPIC -shared -o lib{your_library_name_here}.so

Now in your Cargo.toml file add the following under package:

build = "build.rs"

Then in your build.rs file:

fn main() {
  println!("cargo:rustc-link-search=native={path_to_your_haskell_library_directory}");
  println!("cargo:rustc-link-lib=native={library_name_w/o_lib_and_extension}");
}

This links your Haskell library in at compilation. Now for the actual code itself:

extern crate curryrs;
use curryrs::hsrt::{start,stop};
use curryrs::types::I64;

extern {
  pub fn fourth(x: I64) -> I64;
  pub fn fifth(x: I64) -> I64;
  pub fn sixth(x: I64) -> I64;
}

fn main() {
  // Input is whatever you want to pass to argv whenever
  // you start the Haskell Runtime. You need to start it
  // or calls to Haskell code will fail.
  start("Haskell Functions".to_string());

  println!("2^4 is: {}", unsafe{fourth(2)});
  println!("2^5 is: {}", unsafe{fifth(2)});
  println!("2^6 is: {}", unsafe{sixth(2)});

  // You need to make sure the runtime is stopped
  // otherwise you'll have undefined behavior
  // and wasted resources.
  stop();
}

This makes it easy to do without needing to muck around with linking the right libraries and you're easily able to call the runtime you want.

The library also allows you to choose which version of the Haskell Runtime you want to use. By default it uses the non-threaded version. You can choose which one you want with a feature flag in Cargo.toml

[dependencies]
# If you need the threaded runtime put this:
curryrs = { version = "^0.2.0", features = "threaded" }

# If you need the threaded runtime w/ logging put this:
curryrs = { version = "^0.2.0", features = "threaded_l" }

# If you need the threaded runtime w/ debug output put this:
curryrs = { version = "^0.2.0", features = "threaded_debug" }

Bug Reports

If you encounter errors of any sort please take a look in the issue tracker first. If your error is already there or has been closed before take a look at how it was solved or contribute to the open bug by explaining what has happened while using the library. Duplicates will be marked and closed.

Contributing

See CONTRIBUTING.md for more information.

Tests

See TESTS.md for more information.

Changelog

To see a list of changes between version take a look at CHANGELOG.md for more information.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

You might also like...
Objective-C Runtime bindings and wrapper for Rust.

Objective-C Runtime bindings and wrapper for Rust. Documentation: http://ssheldon.github.io/rust-objc/objc/ Crate: https://crates.io/crates/objc Messa

A minimalist and safe ECS library for rust!
A minimalist and safe ECS library for rust!

The full ECS (Entity-Component-System) library. Support an Open Source Developer! ♥️ Composed of two smaller libraries: world_dispatcher: the System p

A notebook app integrated with todo lists utility. Developed with Rust, WebAssembly, Yew and Trunk.

Flow.er A notebook app integrated with todo-list utility. Project flow.er is a Rust WASM app running in browser. Taking advantage of Yew and Trunk, it

A JavaScript Runtime built with Mozilla's SpiderMonkey Engine and Rust

Spiderfire Spiderfire is a javascript runtime built with Mozilla's SpiderMonkey engine and Rust. Spiderfire aims to disrupt the server-side javascript

A rust library containing typings and utility functions dealing with the Public specification of the Internet Computer.

IC Types Contributing Please follow the guidelines in the CONTRIBUTING.md document. Goal This library contains typings and utility functions dealing w

Modern JavaScript runtime for Sony PSP, based on rust-psp and QuickJS.

PSP.js Modern JavaScript runtime for Sony PSP, based on rust-psp and QuickJS. ⚠️ Currently in PoC state, unusable for developing JavaScript apps yet.

Implementation of the Radon and Inverse Radon Transforms in Rust

Radon Transform A rust and python implementation of the discretized version of the radon transform that I did out of boredom. The main mathematical tr

🚀 Fast and 100% API compatible postcss replacer, built in Rust

postcss-rs 🚀 Fast and 100% API compatible postcss replacer, built in Rust ⚠️ DO NOT USE. STILL WORK IN PROGRESS. Performance Improvement Tokenize boo

A simple programming language made for scripting inspired on rust and javascript.

FnXY Programming Language Quick move: CONTRIBUTING | LICENSE What? FnXY is a simple programming language made for scripting inspired on rust and javas

Releases(v0.2.0)
  • v0.2.0(Oct 26, 2016)

    v0.2.0

    Features

    • Add Haskell Runtime Support to Rust Library
    • Change build.rs script to pull in the base libraries needed to get the Runtime Working.
    • Change structuring of Haskell code so import statements for modules is: haskell import Curryrs.Types and not: haskell import Types

    Documentation

    • Update README with how to properly call Haskell code in Rust with the new library updates by calling the Runtime from within Rust. It also now makes setting up the Haskell code a lot easier removing the need for header files and using gcc to get code to work.

    Testing

    • Setup Haskell in Rust tests with C glue code to get it to work
    Source code(tar.gz)
    Source code(zip)
  • v0.1.1(Oct 26, 2016)

    v0.1.1

    Features

    • Change FFI Primitives to use fixed width versions in Haskell and Rust rather than using C types.

    Documentation

    • Update README to make documentation clearer to users based off feedback in issue #1
    • Update README with how to get Haskell into Rust

    Testing

    • Setup Haskell in Rust tests with C glue code to get it to work
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Oct 9, 2016)

    • Establishes a base library containing primitive types between the two languages.
    • Includes macros to make FFI of functions easier and readable
    • Includes the ability to have it work with stack and cabal
    Source code(tar.gz)
    Source code(zip)
Owner
Michael Gattozzi
Rustacean 🦀"a bad programmer" according to the Orange Site, he/him
Michael Gattozzi
Handy macro to generate C-FFI bindings to Rust for Haskell

hs-bindgen Handy macro to generate C-FFI bindings to Rust for Haskell. This library intended to work best in a project configured by cargo-cabal. N.B.

Yvan Sraka 32 Feb 16, 2023
Safe Rust bridge for creating Erlang NIF functions

Rustler Documentation | Getting Started | Example Rustler is a library for writing Erlang NIFs in safe Rust code. That means there should be no ways t

Rusterlium 3.5k Jan 7, 2023
Safe interop between Rust and C++

CXX — safe FFI between Rust and C++ This library provides a safe mechanism for calling C++ code from Rust and Rust code from C++, not subject to the m

David Tolnay 4.4k Jan 7, 2023
“The Tie Between Ruby and Rust.”

Rutie Rutie — /ro͞oˈˌtī/rOOˈˌtI/rüˈˌtaI/ Integrate Ruby with your Rust application. Or integrate Rust with your Ruby application. This project allows

Daniel P. Clark 726 Jan 2, 2023
Facilitating high-level interactions between Wasm modules and JavaScript

wasm-bindgen Facilitating high-level interactions between Wasm modules and JavaScript. Guide | API Docs | Contributing | Chat Built with ?? ?? by The

Rust and WebAssembly 5.9k Jan 8, 2023
Robust and Fast tokenizations alignment library for Rust and Python

Robust and Fast tokenizations alignment library for Rust and Python Demo: demo Rust document: docs.rs Blog post: How to calculate the alignment betwee

Explosion 157 Dec 28, 2022
Rust Attribute-Based Encryption library rabe's C FFI binding , support CP-ABE and KP-ABE encrypt and decrypt, submodule of Rabe.Core c# library.

Rabe-ffi Rust Attribute-Based Encryption library rabe's C FFI binding , support CP-ABE and KP-ABE encrypt and decrypt, submodule of Rabe.Core c# libra

Aya0wind 2 Oct 10, 2022
Slitter is a C- and Rust-callable slab allocator implemented primarily in Rust, with some C for performance or to avoid unstable Rust features.

Slitter is a less footgunny slab allocator Slitter is a classically structured thread-caching slab allocator that's meant to help write reliable long-

Backtrace Labs 133 Dec 5, 2022
Automatically generates Rust FFI bindings to C (and some C++) libraries.

bindgen bindgen automatically generates Rust FFI bindings to C (and some C++) libraries. For example, given the C header doggo.h: typedef struct Doggo

The Rust Programming Language 3.2k Jan 4, 2023
Rust bindings for writing safe and fast native Node.js modules.

Rust bindings for writing safe and fast native Node.js modules. Getting started Once you have the platform dependencies installed, getting started is

The Neon Project 7k Jan 4, 2023