• Stars
    star
    386
  • Rank 108,195 (Top 3 %)
  • Language
    Haskell
  • Created over 11 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Call Haskell functions from any programming language via serialization and dynamic libraries

call-haskell-from-anything

Build Status

Call Haskell functions from any programming language via serialization and dynamic libraries.

Skip the philosophy, jump right to the code!

I just want to call that function

Want to call Haskell from Python?
Want to call Haskell from Ruby?
Want to call Haskell from C?
Want to call Haskell from Node.js?
Want to call Haskell from C#?
Want to call Haskell from Java?
Want to call Haskell from browsers?

Yes, Haskell can do that.

Using the Foreign Function Interface (FFI) you can expose Haskell functions at the C level.

But damn, it's so hard!

You have two high-level languages here (Haskell and X), but even though you "just want to call that function", you have to think about and write low-level system code on both sides. Going via C is painful: An interface that does not even support the idea of many of something is not very supportive (no, C doesn't even have arrays, it only has pointers to the start of something).

What we really want for most cases:

  • a slightly higher level, intuitive interface
  • as invisible as possible
  • just calling that function.
Want to call Haskell from ... anything?

The simplest FFI: Serialization

In the end, the C calling convention is just another wire format: Data is to be shipped from one function to another.

So we could just as well use a wire format that is not as uncomfortable as the C FFI.

Any serialization library does that for us, and most of them (e.g. JSON) are simpler to reason about and manage than raw memory in C.

call-haskell-from-anything implements FFI function calls where function arguments and return value are serialized using MessagePack. Any function is then exported via the standard FFI as a raw bytes (CString -> IO CString) interface.

Usage

call-haskell-from-anything allows you to write a function, say:

chooseMax :: [Int] -> Int
chooseMax xs = ...

Add this:

foreign export ccall chooseMax_export :: CString -> IO CString
chooseMax_export = export chooseMax

and compile it into a shared library (.so or .dll). You can now call it from any language that supports MessagePack, e.g. Python:

chooseMax = wrap_into_msgpack(cdll.LoadLibrary('mylib.so').chooseMax_export)

print chooseMax([1,5,3])

--

In detail, it will transform your functions of type

f :: a -> b -> ... -> r

to an equivalent (it is actually a type-level list) of

f' :: (a, b, ...) -> r

so that the function input (arguments) can be easily de-serialized.

The wrap_into_msgpack function used above sets the return type of the foreign function to raw bytes and wraps arguments and return value into MessagePack, prepended by a 64-bit length:

def wrap_into_msgpack(foreign_fun):
    foreign_fun.restype = c_char_p

    def wrapped_fun(*args):
        packed = msgpack.packb(args)
        length_64bits = struct.pack("q", len(packed)) # native-endian
        ptr = fun(length_64bits + packed)
        data_length = cast(ptr[:8], POINTER(c_longlong))[0]
        res = msgpack.unpackb(ptr[8:8+data_length])
        free(ptr)
        return res

    return wrapped_fun

A full example

You can run the stock example in this repository:

sudo apt-get install python-msgpack ruby-msgpack  # or equivalent for your system
stack build

# If any of these work, you're all fine!
python test.py
ruby test.rb

FAQ

Is call-haskell-from-anything an RPC framework?

No. RPC means Remote Procedure Call, and nothing in call-haskell-from-anything assumes to be remote.

Calls are blocking as you would expect from standard C libraries.

Are there restrictions on what arguments functions can take?

Yes: all arguments and the return value must be serializable.

This means you cannot pass around pointers or callback functions; you have to use the C style FFI or an RPC mechanism for that.

Why is MsgPack used for serialization?

Because it is simple, available (there are implementations for most programming languages, and writing new ones is easy due to its simplicity), supports dumb binary (passing around arbitrary custom data does not require to think about encoding), and fast (in many implementations).

However, call-haskell-from-anything is not fixed to use only MsgPack as wire-format; anything that can conveniently encode lists/arrays is suitable (FFI.Anything.TypeUncurry.Msgpack is the only implementation so far, though).

How fast are serialized FFI calls? What is the trade-off compared to a C style FFI?

Calls from one programming language into another are usually slower than calls inside the programming language, so it does make sense to check if a foreign call is worth it.

In some preliminary cPython 2.7 benchmark using functions that take a single Int and return a single Int (e.g. the +1 function), a foreign call using MsgPack serialization takes around 15 times longer than an in-Python function call (on the tested Core i5 machine, 1M calls took 15s, in pure Python they took 1s). However, as soon as you perform a somewhat expensive computation, the call into native Haskell code becomes worth it (take for example a naive recursive fibonacci implementation for 100000 calls of fib(15); in-Python: 90s, with call-haskell-from-anything: 4.5s).

In comparison to a C style FFI to an immediately returning Int -> Int function, the overhead of a serializing function call is around 6 times higher, and, as usual, becomes insignificant as soon as the function does something.

More detailed benchmarks are planned, and contributions are welcome.

More Repositories

1

static-haskell-nix

easily build most Haskell programs into fully static Linux executables
Nix
365
star
2

strace-pipes-presentation

Presentation: Debugging across pipes and sockets with strace
Python
149
star
3

hatrace

scriptable strace
Haskell
120
star
4

nixops-tutorial

Tutorial for practical deployments with NixOps
Nix
108
star
5

haskell-cpu-instruction-counter

Measuring CPU instructions in Haskell using Linux Performance Counters
Haskell
85
star
6

haskell-from-python

Example how to call Haskell from Python easily (using ctypes.cdll.LoadLibrary)
Haskell
60
star
7

nix-binary-cache-proxy

An NGINX caching proxy to serve the cache.nixos.org binary cache from your local network, ready-to-deploy with nixops
Nix
51
star
8

link-with-lld-example

Example how to link Haskell programs very quickly with lld
Haskell
47
star
9

haskell-jobs-statistics

37
star
10

haskell-ordnub

Data.List.nub is O(n²). This one is O(n log n) by requiring an Ord instance.
HTML
31
star
11

hemokit

Haskell library for the Emotiv EEG, inspired by the Emokit code
Haskell
31
star
12

nixos-vm-examples

Examples of how to build and run NixOS VMs with nix
Nix
28
star
13

nixos-ami-building

Methods for building custom NixOS AMIs
Shell
25
star
14

housescan

Building-scale interior 3D reconstruction with KinectFusion
Haskell
22
star
15

arduino-a7105

Fixed code from http://www.instructables.com/id/Easy-Android-controllable-PC-Interfaceable-Relati/step6/Arduino-Software/
Arduino
22
star
16

asus-xtion-fix

For making the Asus Xtion work on USB 3.0 on Linux (e.g. for PCL)
17
star
17

loop

Fast loops for Haskell (for when GHC can't optimize forM_), with benchmarks
HTML
17
star
18

gmail-spamfilters-paypal-security-messages

Screenshot of how GMail classified PayPal security message as spam
16
star
19

hackage-download

Script to download all of Hackage
Python
14
star
20

dentls

Fixed version of the program at https://serverfault.com/a/328305/128321
C
14
star
21

haskellerz-async-tutorial-2020

Async tutorial (my HaskellerZ 2020 talk)
Haskell
13
star
22

network-house

Haskell data structures and parsers for Ethernet, TCP, UDP, IPv4, IPv6, ICMP, DHCP, and TFTP packages. Extracted from the House project network stack.
Haskell
13
star
23

diskorder

read files in physical order to reduce hard drive seeks
Python
12
star
24

aesonbson

Mapping between Aeson's JSON and Bson objects
Haskell
11
star
25

haskell-static-data-sqlite

Example how to append data to a Haskell executable using sqlite
C
11
star
26

niceshare

GUI for gstreamer-based screen sharing
Python
10
star
27

shared-memory

Haskell shared memory library
Haskell
10
star
28

sublime-text-move-tabs

Arranging tabs in Sublime Text like in Chrome
Python
9
star
29

conduit-concurrent-map

Concurrent, order-preserving mapping Conduit for Haskell
Haskell
8
star
30

kibana-importer

Imports a Kibana export.json file into Kibana
Python
8
star
31

nixops-gluster-example

Advanced nixops deployment example: GlusterFS
Nix
7
star
32

iso8601-time

Convert to/from the ISO 8601 time format in Haskell
Haskell
6
star
33

lambdabot-zulip

Lambdabot for Zulip Chat
Haskell
6
star
34

haskell-todos

nh2's Haskell TODO / wish list for Open Source tasks to improve Haskell
6
star
35

eventstreamexamples

Example Turbogears project for implementing server-side events in Python
Python
6
star
36

call-python-via-msgpack

Call Python from Haskell by FFI-via-serialisation over MessagePack
Haskell
6
star
37

custom-hackage

Script that allows to run your own hackage with select packages/versions that you drop in
Shell
6
star
38

ghc-mod-socket

Makes ghc-modi behave like hdevtools
Haskell
6
star
39

ar-timestamp-wiper

Wipes time stamps from .a files (like ar -D)
Haskell
5
star
40

proctest

A Haskell library for testing interactive command line programs
Haskell
5
star
41

nixos-configs

My NixOS configs
Nix
5
star
42

selfrestart

Allows restarting the currently running Haskell executable
Haskell
5
star
43

lz4-frame-conduit

Haskell Conduit implementing the official LZ4 frame streaming format
Haskell
5
star
44

git-rewrite-history-on-patches

Script to replace words in a range of recent git commits
Python
4
star
45

chrubuntu-anyos

Run any Linux distro on your legacy Chromebook, ChrUbuntu style
Nix
4
star
46

multishake

A Shake build system that builds a cabal project together with a set of dependencies available in source
Haskell
4
star
47

darcs-fastconvert

Import/export git repos to/from darcs. Also contains darcs-bridge for bidirectional synchronisation. Forked from http://darcsden.com/mornfall/darcs-fastconvert to fix build on newer platforms.
Haskell
4
star
48

stack-nix-caching-example

Example of how to use nix Haskell binary packages with stack
Nix
3
star
49

haskell-netpbm

Loading PBM, PGM, PPM image files in pure Haskell
Haskell
3
star
50

nixos-blockdevice-attachment-explanations

Article about block device file-system auto-creation on NixOS
3
star
51

quadcopter-simulation

Rust
3
star
52

nixos-vm-building

Example of how to iterate on a NixOS config in a local VM.
Shell
3
star
53

vinput

Virtual input devices on Linux for multitouch tables and other funny stuff.
Python
3
star
54

sublime-toggle-line-numbers

Adds a command to enable/disable line numbers for the current buffer.
Python
3
star
55

Abacus

A Better Alignment Plugin for Sublime Text 2 `⌘⌥^ ]`
Python
3
star
56

hello_wayland_haskell

Example Wayland program (client) in Haskell
Haskell
2
star
57

blog

nh2's blog posts
Haskell
2
star
58

haskell-pdxhouse

Git mirror of the Haskell House operating system project (https://code.google.com/p/pdxhouse)
Haskell
2
star
59

bupstash-kopia-comparison

Evaluation benchmarks of backup tools bupstash and kopiia
2
star
60

wordwang

Haskell
2
star
61

reinterpret-cast

Memory reinterpretation casts for Float/Double and Word32/Word64 in Haskell
HTML
2
star
62

KinectStreamer

Streams Kinect data (such as the depth image) as a TCP server
C#
2
star
63

lambdanumbers

Haskell
2
star
64

staticfetcher

Fetches static files.
Python
2
star
65

jsschema

Object structure checking for the rescue!
JavaScript
2
star
66

AntiMersenne

Predicting Python's Mersenne twister PRNG for 30c3 CTF, with Python calling Java, yeah
Java
2
star
67

temperature-sensor-server

Haskell server to serve temperature from Arduino
Haskell
2
star
68

obse

Git mirror of the Oblivion Script Extender (http://obse.silverlock.org)
C++
2
star
69

dsa42

Spieleprogrammieren im Kurs "Extreme Programming" auf der Deutschen Schülerakademie Schelklingen 2008
Java
2
star
70

linux-bad-core-scheduling-investigation

Write-up of a Linux kernel bisection to find a scheduler bug that results in reduced performance
Python
2
star
71

cv

JavaScript
2
star
72

udp-splitter

Haskell program to forward incoming UDP packets to N many targets
Haskell
2
star
73

ghc-generics-deriving-is-slow

Reproduction for `deriving Generic` being quadratic in the Glorious Haskell Compiler
Haskell
2
star
74

empty-angular-project

A browser project template using: angular, coffeescript, stylus, testacular, bower, grunt.
CoffeeScript
2
star
75

psqueue-benchmarks

Benchmark of Haskell Priority Search Queue implementations
Haskell
2
star
76

flippi

Flippi: a Wiki clone written in Haskell (http://www.flippac.org/projects/flippi/). I have nothing to do with this project nor do I maintain it - I just fixed the build because someone in Haskell-Cafe had a problem with that.
Haskell
2
star
77

inner-loop-benchmarks

Criterion benchmarks for http://neilmitchell.blogspot.co.uk/2014/01/optimising-haskell-for-tight-inner-loop.html
Haskell
1
star
78

hspec-experiment

Test trees as modifiable data for hspec
Haskell
1
star
79

WashNGo

A Haskell EDSL for programming Web applications. I have nothing to do with this project nor do I maintain it - I just fixed the build because someone in Haskell-Cafe had a problem with that.
Haskell
1
star
80

dig-5-seconds-hang

Linux kernel dropped DNS requests investigation (visible to iptables but not Wireshark)
1
star
81

deadpager

Dead-man's-switch notification system with High-Availability deployment
Haskell
1
star
82

gtkpasswordentry

A GTK text box for passwords with an icon to show the password in plain text
C
1
star
83

e57-dump

Simple executable to dump .e57 file structure as text for quick inspection
Meson
1
star
84

infinite-type-families

Some problems I'm encountering with GHC 7.7
Haskell
1
star
85

copier

Tool to copy files in parallel for use on networked file systems. Written in Haskell
Haskell
1
star
86

parallel-map-experiments

Haskell experiments around monad-par, parallel, parMap and spark scheduling
Haskell
1
star
87

haskell-socketio

(Unfinished) Haskell server-side engine.io and socket.io implementation. Avoids real-time at all cost!
Haskell
1
star
88

ghc-bug-th-loading

Test case for a GHC bug concerning the unnecessary loading packages when TH is used
Haskell
1
star
89

ghc-control-monad-trans-unlift-stack-overflow

Reproduction for GHC 8.0 stack overflow
Haskell
1
star
90

thinkpadlight-client

A simple library use thinkpadlightd
Python
1
star
91

ghc-omit-interface-pragmas-dsImpSpecs-bug

Repro for GHC 7.8.4 panic: dsImpSpecs on SPECIALISE pragma with -fhpc enabled
Haskell
1
star
92

jquery-elastic

JavaScript
1
star
93

futhark-featurematch-2nn

Futhark implementation of two-nearest-neighbour brute-force quadratic feature matching.
Futhark
1
star
94

number-streams

Haskell library for calculating properties on streams of numbers, e.g. moving sums and averages
Haskell
1
star
95

getDirectoryContents-benchmarks

Benchmarking Haskell's getDirectoryContents function and alternatives
Haskell
1
star
96

onezerocat

Tools for translating binary files into 1-0-sequences and vice versa
Python
1
star
97

jquery-doublepostpreventer

Disabling submit buttons after submit
JavaScript
1
star
98

haskell-quickselect-median-of-medians

O(n) Quickselect algorithm with median-of-medians in Haskell
Haskell
1
star
99

thinkpadlightd

A server for your ThinkPad's enlightenment
Python
1
star
100

u51

Web password manager written in Python/Django
JavaScript
1
star