Code Monkey home page Code Monkey logo

call-haskell-from-anything's Introduction

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.

call-haskell-from-anything's People

Contributors

jsl avatar nh2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

call-haskell-from-anything's Issues

Windows build possibility

It is not possible to build for windows. Please add the possibility to build for windows by cabal install call-haskell-from-anything or cabal build?

Travis build fails on ghc 7.8

I just restarted this build, which was green before, and now it fails on GHC 7.8 while exactly the same code worked perfectly just a few days ealier:

The command "cabal build" exited with 0.
$ python test.py
Traceback (most recent call last):
  File "test.py", line 4, in <module>
    lib = cdll.LoadLibrary("dist/build/call-haskell-from-anything.so/call-haskell-from-anything.so")
  File "/usr/lib/python2.7/ctypes/__init__.py", line 443, in LoadLibrary
    return self._dlltype(name)
  File "/usr/lib/python2.7/ctypes/__init__.py", line 365, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: libHScall-haskell-from-anything-0.1.0.1-ghc7.8.3.so: cannot open shared object file: No such file or directory

No clue yet what's going on.

Encounter Error when trying to load .so file

Hey,

I created a simple Haskell file containing one function and the

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

part from the readme. Then I compiled it to a .so with:

sudo ghc --make -dynamic -shared -fPIC Java2Haskell.hs -o Java2Haskell.so

when I try to load it in Python or Java I encounter this error:

Traceback (most recent call last):
File "test.py", line 15, in <module>
lib = cdll.LoadLibrary(so_file_path)
File "/usr/lib/python2.7/ctypes/__init__.py", line 443, in LoadLibrary
return self._dlltype(name)
File "/usr/lib/python2.7/ctypes/__init__.py", line 365, in __init__
self._handle = _dlopen(self._name, mode)
OSError: /usr/lib/ghc/ghcpr_8TmvWUcS1U1IKHT0levwg3/libHSghc-prim-0.4.0.0-8TmvWUcS1U1IKHT0levwg3-ghc7.10.3.so: undefined symbol: stg_forkOnzh

decoding problem with doubles

using this haskell:

foreign export ccall iddub_export :: CString -> IO CString
iddub_export = export iddub
iddub :: Double -> Double
iddub = id

and this python

# Some shortcuts
def make_msgpack_fun(fun):
    fun.restype = c_char_p

    def f(*args):
        return msgpack.unpackb(fun(msgpack.packb(args)))

    return f

iddub = make_msgpack_fun(lib.iddub_export)
for i in [1.01,1.001,1.0001]:
    print(i)
    print(iddub(i))

i get this rather weird message:

1.01
1.01
1.001
1.001
1.0001
<unknown>: Data.Binary.Get.runGet at position 1: Data.Binary.Get(Alternative).empty
CallStack (from HasCallStack):
  error, called at src/Data/Binary/Get.hs:321:5 in binary-0.7.6.1-A5o7SPwyA2mJ8cbNniVomK:Data.Binary.Get

could the parsing of floats be wrong somehow? it also happens with 1.0.

Build failure on GHC 7.10.3

$ stack build
call-haskell-from-anything-1.0.1.0: configure
Configuring call-haskell-from-anything-1.0.1.0...
Determining GHC version: 7.10.3
setup: Missing dependency on a foreign library:
* Missing C library: HSrts-ghc7.10.3
This problem can usually be solved by installing the system package that
provides this library (you may need the "-dev" version). If the library is
already installed but in a non-standard location then you can use the flags
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.

--  While building package call-haskell-from-anything-1.0.1.0 using:
      /tmp/call-haskell-from-anything/.stack-work/dist/x86_64-linux/Cabal-1.22.5.0/setup/setup --builddir=.stack-work/dist/x86_64-linux/Cabal-1.22.5.0 configure --with-ghc=/usr/bin/ghc --with-ghc-pkg=/usr/bin/ghc-pkg --user --package-db=clear --package-db=global --package-db=/home/auke/.stack/snapshots/x86_64-linux/lts-5.0/7.10.3/pkgdb --package-db=/tmp/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/pkgdb --libdir=/tmp/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/lib --bindir=/tmp/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/bin --datadir=/tmp/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/share --libexecdir=/tmp/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/libexec --sysconfdir=/tmp/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/etc --docdir=/tmp/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/doc/call-haskell-from-anything-1.0.1.0 --htmldir=/tmp/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/doc/call-haskell-from-anything-1.0.1.0 --haddockdir=/tmp/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/doc/call-haskell-from-anything-1.0.1.0 --dependency=base=base-4.8.2.0-0d6d1084fbc041e1cded9228e80e264d --dependency=bytestring=bytestring-0.10.6.0-c60f4c543b22c7f7293a06ae48820437 --dependency=msgpack=msgpack-1.0.0-35bd85d7f20379ce49d93358b7384422 --dependency=mtl=mtl-2.2.1-3af90341e75ee52dfc4e3143b4e5d219 --dependency=template-haskell=template-haskell-2.10.0.0-3c4cb52230f347282af9b2817f013181 --dependency=vector=vector-0.11.0.0-299aefb173ce5a731565d31f609a0cfd --enable-tests --enable-benchmarks
    Process exited with code: ExitFailure 1

A simple (sandboxed) cabal build fails on a first run, and succeeds on a second.

(cabal install fails, even on second try: it seems to run a clean build, which apparently doesn't work)

cannot satisfy -package Cabal-1.24.1.0

Hey guys,

When following the installation instructions, I am getting this:

> stack build

msgpack-1.0.0: configure
msgpack-1.0.0: build
msgpack-1.0.0: copy/register
call-haskell-from-anything-1.0.1.0: configure
<command line>: cannot satisfy -package Cabal-1.24.1.0: 
    Cabal-1.24.1.0-IVPBR8CshIb24I8NwtoMDO is unusable due to missing or recursive dependencies:
      binary-0.7.5.0-bf6a937522bb8cec5d00218470f28789
    (use -v for more information)
Completed 2 action(s).

--  While building package call-haskell-from-anything-1.0.1.0 using:
      /home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/bin/ghc --make -odir /home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/dist/x86_64-linux/Cabal-1.24.1.0/setup -hidir /home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/dist/x86_64-linux/Cabal-1.24.1.0/setup -i -i. -package=Cabal-1.24.1.0 -clear-package-db -global-package-db -package-db=/home/madjestic/.stack/snapshots/x86_64-linux/lts-5.0/7.10.3/pkgdb /home/madjestic/Projects/Haskell/call-haskell-from-anything/Setup.hs -o /home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/dist/x86_64-linux/Cabal-1.24.1.0/setup/setup
    Process exited with code: ExitFailure 1

Here's my stack.yaml:

resolver: lts-5.0
extra-deps:
- msgpack-1.0.0

Here's the verbose version:

stack -v build
Version 1.1.2 x86_64 hpack-0.14.1
2016-11-29 17:06:40.562900: [debug] Checking for project config at: /home/madjestic/Projects/Haskell/call-haskell-from-anything/stack.yaml @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Config src/Stack/Config.hs:811:9)
2016-11-29 17:06:40.563274: [debug] Loading project config file stack.yaml @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Config src/Stack/Config.hs:829:13)
2016-11-29 17:06:40.565252: [debug] Checking whether stack was built with libgmp4 @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Config src/Stack/Config.hs:326:5)
2016-11-29 17:06:40.565398: [debug] Run process: ldd /usr/bin/stack @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:System.Process.Read src/System/Process/Read.hs:283:3)
2016-11-29 17:06:40.606471: [debug] Stack was not built with libgmp4 @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Config src/Stack/Config.hs:330:14)
2016-11-29 17:06:40.606863: [debug] Trying to decode /home/madjestic/.stack/build-plan-cache/x86_64-linux/lts-5.0.cache @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Data.Binary.VersionTagged src/Data/Binary/VersionTagged.hs:55:5)
2016-11-29 17:06:40.621424: [debug] Success decoding /home/madjestic/.stack/build-plan-cache/x86_64-linux/lts-5.0.cache @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Data.Binary.VersionTagged src/Data/Binary/VersionTagged.hs:64:13)
2016-11-29 17:06:40.621726: [debug] Getting system compiler version @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Setup src/Stack/Setup.hs:341:17)
2016-11-29 17:06:40.621937: [debug] Run process: ghc --info @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:System.Process.Read src/System/Process/Read.hs:283:3)
2016-11-29 17:06:40.676719: [debug] Asking GHC for its version @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Setup.Installed src/Stack/Setup/Installed.hs:94:13)
2016-11-29 17:06:40.676979: [debug] Run process: ghc --numeric-version @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:System.Process.Read src/System/Process/Read.hs:283:3)
2016-11-29 17:06:40.710510: [debug] Getting Cabal package version @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.GhcPkg src/Stack/GhcPkg.hs:165:5)
2016-11-29 17:06:40.710830: [debug] Run process: ghc-pkg --no-user-package-db field --simple-output Cabal version @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:System.Process.Read src/System/Process/Read.hs:283:3)
2016-11-29 17:06:40.737381: [debug] Resolving package entries @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Setup src/Stack/Setup.hs:221:5)
2016-11-29 17:06:40.738336: [debug] Getting global package database location @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.GhcPkg src/Stack/GhcPkg.hs:48:5)
2016-11-29 17:06:40.738502: [debug] Run process: ghc-pkg --no-user-package-db list --global @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:System.Process.Read src/System/Process/Read.hs:283:3)
2016-11-29 17:06:40.781933: [debug] Run process: ghc-pkg --global --no-user-package-db dump --expand-pkgroot @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:System.Process.Read src/System/Process/Read.hs:283:3)
2016-11-29 17:06:40.835289: [debug] Ignoring package Cabal due to wanting version 1.22.7.0 instead of 1.24.0.0 @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Build.Installed src/Stack/Build/Installed.hs:189:5)
2016-11-29 17:06:40.835507: [debug] Ignoring package haskeline due to wanting version 0.7.2.2 instead of 0.7.2.1 @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Build.Installed src/Stack/Build/Installed.hs:189:5)
2016-11-29 17:06:40.835628: [debug] Ignoring package terminfo due to wanting version 0.4.0.2 instead of 0.4.0.1 @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Build.Installed src/Stack/Build/Installed.hs:189:5)
2016-11-29 17:06:40.836055: [debug] Ignoring package Cabal due to wanting version 1.22.7.0 instead of 1.22.5.0 @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Build.Installed src/Stack/Build/Installed.hs:189:5)
2016-11-29 17:06:40.836303: [debug] Run process: ghc-pkg --user --no-user-package-db --package-db /home/madjestic/.stack/snapshots/x86_64-linux/lts-5.0/7.10.3/pkgdb dump --expand-pkgroot @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:System.Process.Read src/System/Process/Read.hs:283:3)
2016-11-29 17:06:40.863166: [debug] Run process: ghc-pkg --user --no-user-package-db --package-db /home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/pkgdb dump --expand-pkgroot @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:System.Process.Read src/System/Process/Read.hs:283:3)
2016-11-29 17:06:40.889667: [debug] Trying to decode /home/madjestic/.stack/indices/Hackage/00-index.cache @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Data.Binary.VersionTagged src/Data/Binary/VersionTagged.hs:55:5)
2016-11-29 17:06:41.171811: [debug] Success decoding /home/madjestic/.stack/indices/Hackage/00-index.cache @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Data.Binary.VersionTagged src/Data/Binary/VersionTagged.hs:64:13)
2016-11-29 17:06:41.192075: [debug] Getting global package database location @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.GhcPkg src/Stack/GhcPkg.hs:48:5)
2016-11-29 17:06:41.192235: [debug] Run process: ghc-pkg --no-user-package-db list --global @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:System.Process.Read src/System/Process/Read.hs:283:3)
2016-11-29 17:06:41.218921: [info] call-haskell-from-anything-1.0.1.0: configure @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Build.Execute src/Stack/Build/Execute.hs:731:23)
2016-11-29 17:06:41.219584: [debug] Run process: /home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/bin/ghc --make -odir /home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/dist/x86_64-linux/Cabal-1.24.1.0/setup -hidir /home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/dist/x86_64-linux/Cabal-1.24.1.0/setup -i -i. -package=Cabal-1.24.1.0 -clear-package-db -global-package-db -package-db=/home/madjestic/.stack/snapshots/x86_64-linux/lts-5.0/7.10.3/pkgdb /home/madjestic/Projects/Haskell/call-haskell-from-anything/Setup.hs -o /home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/dist/x86_64-linux/Cabal-1.24.1.0/setup/setup @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:System.Process.Read src/System/Process/Read.hs:283:3)
2016-11-29 17:06:41.262246: [warn] <command line>: cannot satisfy -package Cabal-1.24.1.0:  @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Build.Execute src/Stack/Build/Execute.hs:911:67)
2016-11-29 17:06:41.262840: [warn]     Cabal-1.24.1.0-IVPBR8CshIb24I8NwtoMDO is unusable due to missing or recursive dependencies: @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Build.Execute src/Stack/Build/Execute.hs:911:67)
2016-11-29 17:06:41.262992: [warn]       binary-0.7.5.0-bf6a937522bb8cec5d00218470f28789 @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Build.Execute src/Stack/Build/Execute.hs:911:67)
2016-11-29 17:06:41.263095: [warn]     (use -v for more information) @(stack-1.1.2-2hdiqRkX9Pm45LigLCmMXh:Stack.Build.Execute src/Stack/Build/Execute.hs:911:67)

--  While building package call-haskell-from-anything-1.0.1.0 using:
      /home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/bin/ghc --make -odir /home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/dist/x86_64-linux/Cabal-1.24.1.0/setup -hidir /home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/dist/x86_64-linux/Cabal-1.24.1.0/setup -i -i. -package=Cabal-1.24.1.0 -clear-package-db -global-package-db -package-db=/home/madjestic/.stack/snapshots/x86_64-linux/lts-5.0/7.10.3/pkgdb /home/madjestic/Projects/Haskell/call-haskell-from-anything/Setup.hs -o /home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/dist/x86_64-linux/Cabal-1.24.1.0/setup/setup
    Process exited with code: ExitFailure 1

Remove need to wrap pure functions into Identity monad

Currently we can only export functions of type a -> b -> ... -> Identity r, which is quite lame.

We want to be able to directly export functions of type a -> b -> ... -> r.

This is because in the conventional (open) type families, you can't have a recursive case on a -> b and a base case of r, sice a -> b and r unify. Thus the base case so far is Identity r.

Closed type families, introduced in GHC 7.8 allow making r the base case.

We should use this to lift this restriction in call-haskell-from-anything.

setup: Missing dependency on a foreign library: * Missing C library: HSrts-ghc7.10.3

Hey guys,

here's my stack.yaml:

resolver: lts-5.0
extra-deps:
- msgpack-1.0.0
ghc-options:
  package-name: -lHSrts-ghc7.10.3

here's my call-haskell-from-anything.buildinfo:

executable: call-haskell-from-anything.so
extra-libraries: HSrts-ghc7.10.3

Here's the errors:

cabal build
Package has never been configured. Configuring with default flags. If this
fails, please run configure manually.
Resolving dependencies...
Configuring call-haskell-from-anything-1.0.1.0...
Determining GHC version: 8.0.1
cabal: Missing dependency on a foreign library:
* Missing C library: HSrts-ghc8.0.1
This problem can usually be solved by installing the system package that
provides this library (you may need the "-dev" version). If the library is
already installed but in a non-standard location then you can use the flags
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.
 stack build
call-haskell-from-anything-1.0.1.0: configure
Configuring call-haskell-from-anything-1.0.1.0...
Determining GHC version: 7.10.3
setup: Missing dependency on a foreign library:
* Missing C library: HSrts-ghc7.10.3
This problem can usually be solved by installing the system package that
provides this library (you may need the "-dev" version). If the library is
already installed but in a non-standard location then you can use the flags
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.

--  While building package call-haskell-from-anything-1.0.1.0 using:
      /home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/dist/x86_64-linux/Cabal-1.22.5.0/setup/setup --builddir=.stack-work/dist/x86_64-linux/Cabal-1.22.5.0 configure --with-ghc=/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/bin/ghc --with-ghc-pkg=/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/bin/ghc-pkg --user --package-db=clear --package-db=global --package-db=/home/madjestic/.stack/snapshots/x86_64-linux/lts-5.0/7.10.3/pkgdb --package-db=/home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/pkgdb --libdir=/home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/lib --bindir=/home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/bin --datadir=/home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/share --libexecdir=/home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/libexec --sysconfdir=/home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/etc --docdir=/home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/doc/call-haskell-from-anything-1.0.1.0 --htmldir=/home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/doc/call-haskell-from-anything-1.0.1.0 --haddockdir=/home/madjestic/Projects/Haskell/call-haskell-from-anything/.stack-work/install/x86_64-linux/lts-5.0/7.10.3/doc/call-haskell-from-anything-1.0.1.0 --dependency=base=base-4.8.2.0-0d6d1084fbc041e1cded9228e80e264d --dependency=bytestring=bytestring-0.10.6.0-9a873bcf33d6ce2fd2698ce69e2c1c66 --dependency=msgpack=msgpack-1.0.0-2b637136678add26d712aa9036257898 --dependency=mtl=mtl-2.2.1-3af90341e75ee52dfc4e3143b4e5d219 --dependency=template-haskell=template-haskell-2.10.0.0-3c4cb52230f347282af9b2817f013181 --dependency=vector=vector-0.11.0.0-299aefb173ce5a731565d31f609a0cfd --enable-tests --enable-benchmarks
    Process exited with code: ExitFailure 1

Here's where HSrts at:

 locate HSrts
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts-ghc7.10.3.so
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts.a
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_debug-ghc7.10.3.so
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_debug.a
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_l-ghc7.10.3.so
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_l.a
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_p.a
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_thr-ghc7.10.3.so
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_thr.a
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_thr_debug-ghc7.10.3.so
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_thr_debug.a
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_thr_l-ghc7.10.3.so
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_thr_l.a
/home/madjestic/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/rts/libHSrts_thr_p.a
/usr/lib64/ghc-8.0.1/rts/libHSrts-ghc8.0.1.so
/usr/lib64/ghc-8.0.1/rts/libHSrts.a
/usr/lib64/ghc-8.0.1/rts/libHSrts_debug-ghc8.0.1.so
/usr/lib64/ghc-8.0.1/rts/libHSrts_debug.a
/usr/lib64/ghc-8.0.1/rts/libHSrts_l-ghc8.0.1.so
/usr/lib64/ghc-8.0.1/rts/libHSrts_l.a
/usr/lib64/ghc-8.0.1/rts/libHSrts_p.a
/usr/lib64/ghc-8.0.1/rts/libHSrts_thr-ghc8.0.1.so
/usr/lib64/ghc-8.0.1/rts/libHSrts_thr.a
/usr/lib64/ghc-8.0.1/rts/libHSrts_thr_debug-ghc8.0.1.so
/usr/lib64/ghc-8.0.1/rts/libHSrts_thr_debug.a
/usr/lib64/ghc-8.0.1/rts/libHSrts_thr_l-ghc8.0.1.so
/usr/lib64/ghc-8.0.1/rts/libHSrts_thr_l.a
/usr/lib64/ghc-8.0.1/rts/libHSrts_thr_p.a

How can I fix this?

Thanks!

How to expose structure/records in C's struct ?

Great work for this library !

How to map a record type in haskell to C's struct ?

I would like to let user to build a record type in Haskell via Python/ctypes, but in example there is only CString example

Overlapping Instances

I have built a very minimal example where I am having trouble with overlapping instances using exportIO. I'm probably doing something dumb so sorry if my error is obvious.

minimal/minimal.hs:14:13:
    Overlapping instances for FFI.Anything.TypeUncurry.DataKinds.ToTypeList
                                (IO ()) '[] (IO ())
      arising from a use of ‘exportIO’
    Matching instances:
      instance (FFI.Anything.TypeUncurry.DataKinds.Param f ~ '[],
                FFI.Anything.TypeUncurry.DataKinds.Result f ~ r, f ~ r) =>
               FFI.Anything.TypeUncurry.DataKinds.ToTypeList f '[] r
        -- Defined in ‘FFI.Anything.TypeUncurry.DataKinds’
      instance FFI.Anything.TypeUncurry.DataKinds.ToTypeList
                 (IO r) '[] (IO r)
        -- Defined in ‘FFI.Anything.TypeUncurry.DataKinds’
    In the expression: exportIO io
    In an equation for ‘io_export’: io_export = exportIO io

minimal.hs

{-# LANGUAGE ForeignFunctionInterface #-}

module Minimal where

import Foreign.C
import FFI.Anything.TypeUncurry.Msgpack

io :: IO ()
io = do
  return ()

foreign export ccall io_export :: CString -> IO CString
io_export :: CString -> IO CString
io_export = exportIO io

from .cabal file

executable minimal.so
  default-language:    Haskell2010
  hs-source-dirs: minimal
  main-is: minimal.hs
  build-depends:
    base ==4.8.2.0
    , call-haskell-from-anything ==1.0.0.0
  ghc-options:
    -no-hs-main -O2 -fPIC -shared -dynamic
  extra-libraries:
    HSrts-ghc7.10.3

Missing dependency on a foreign library

I tried to install the package with CygWin on Windows 10 and got the following error:

Determining GHC version: 8.0.1
cabal.exe: Missing dependency on a foreign library:
* Missing C library: HSrts-ghc8.0.1
This problem can usually be solved by installing the system package that
provides this library (you may need the "-dev" version). If the library is
already installed but in a non-standard location then you can use the flags
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.
cabal: Leaving directory 'C:\Users\Manfred\AppData\Local\Temp\cabal-tmp-1208\call-haskell-from-anything-1.0.1.0'
cabal: Error: some packages failed to install:
call-haskell-from-anything-1.0.1.0 failed during the configure step. The
exception was:
ExitFailure 1

With the use of Cygwin i solved the problem with the configure script in issue #13.
Where is the location of this HSrts-ghc8.0.1 library by default?

Exporting own "data" type

I am trying to export a module with own types with the following code:

{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE TemplateHaskell #-}

module RectangleMover where

import Foreign.C
import FFI.Anything.TypeUncurry.Msgpack

data Point = Point Int Int
movePoint :: Point -> Int -> Int -> Point
movePoint (Point x y) dx dy = Point (x + dx) (y + dy)

data Rectangle = Rectangle { corner :: Point, width :: Int, height :: Int }
move :: Rectangle -> Int -> Int -> Rectangle
move r@(Rectangle {corner=c}) dx dy = r { corner = movePoint c dx dy }

foreign export ccall move_export :: CString -> IO CString
move_export :: CString -> IO CString
move_export = export move

But when i try to compile this i get the this error message:

[1 of 1] Compiling RectangleMover ( test.hs, test.o )

test.hs:19:15:
No instance for (Data.MessagePack.Object.MessagePack Rectangle)
arising from a use of ‘export’
In the expression: export move
In an equation for ‘move_export’: move_export = export move

What am i missing? Or does this package support exporting own types at all?

Update to msgpack-1.0

Development on the mspack has recently resumed with msgpack-1.0.0 being released.

call-haskell-from-anything should be updated to this, in particular because the new version is compatible with newer libraries without --allow-newer (I'm using it here in Travis, and have asked for a point release to 0.7 here to fix these problems).

This will need a bit of work though becasue the new version updated to using binary for the Unpacker.

I'm not going to work on this very soon, unless somebody needs this urgently - in this case ping me here in this issue. PRs are also welcome.

Returning complex objects.

Hi, it'e me again. I'm not sure this is the right place for my question but I'll just go ahead and ask. I've been playing around with this library extensively and I am running into trouble when returning more complex objects.

That bites me already when returning something like [0] from a function. The ffi (i.e. in Ruby) assumes it encountered the end of the string when it finds null somewhere along the way which breaks deserialization (at least I think that's what's happening). I don't really see a viable workaround. I would want to return the size of the message along with the message but I have no idea how to do that. Are there other workarounds? Am I completely missing a point here?

Thanks for your time.

python2: command not found

> stack install call-haskell-from-anything
groom-0.1.2.1: configure
data-msgpack-types-0.0.1: download
groom-0.1.2.1: build
storable-endian-0.2.6: configure
storable-endian-0.2.6: build
data-binary-ieee754-0.4.4: configure
data-binary-ieee754-0.4.4: build
data-msgpack-types-0.0.1: configure
groom-0.1.2.1: copy/register
data-msgpack-types-0.0.1: build
data-binary-ieee754-0.4.4: copy/register
storable-endian-0.2.6: copy/register
data-msgpack-types-0.0.1: copy/register
data-msgpack-0.0.11: download
data-msgpack-0.0.11: configure
data-msgpack-0.0.11: build
data-msgpack-0.0.11: copy/register
call-haskell-from-anything-1.1.0.0: configure
Completed 6 action(s).

--  While building custom Setup.hs for package call-haskell-from-anything-1.1.0.0 using:
      /private/var/folders/zj/p9mj9djj3c3b4vjw5yzq1ckr0000gn/T/stack90413/call-haskell-from-anything-1.1.0.0/.stack-work/dist/x86_64-osx/Cabal-2.0.1.0/setup/setup --builddir=.stack-work/dist/x86_64-osx/Cabal-2.0.1.0 configure --with-ghc=/Users/williamrusnack/.stack/programs/x86_64-osx/ghc-8.2.2/bin/ghc --with-ghc-pkg=/Users/williamrusnack/.stack/programs/x86_64-osx/ghc-8.2.2/bin/ghc-pkg --user --package-db=clear --package-db=global --package-db=/Users/williamrusnack/.stack/snapshots/x86_64-osx/lts-11.16/8.2.2/pkgdb --package-db=/Users/williamrusnack/.stack/global-project/.stack-work/install/x86_64-osx/lts-11.16/8.2.2/pkgdb --libdir=/Users/williamrusnack/.stack/global-project/.stack-work/install/x86_64-osx/lts-11.16/8.2.2/lib --bindir=/Users/williamrusnack/.stack/global-project/.stack-work/install/x86_64-osx/lts-11.16/8.2.2/bin --datadir=/Users/williamrusnack/.stack/global-project/.stack-work/install/x86_64-osx/lts-11.16/8.2.2/share --libexecdir=/Users/williamrusnack/.stack/global-project/.stack-work/install/x86_64-osx/lts-11.16/8.2.2/libexec --sysconfdir=/Users/williamrusnack/.stack/global-project/.stack-work/install/x86_64-osx/lts-11.16/8.2.2/etc --docdir=/Users/williamrusnack/.stack/global-project/.stack-work/install/x86_64-osx/lts-11.16/8.2.2/doc/call-haskell-from-anything-1.1.0.0 --htmldir=/Users/williamrusnack/.stack/global-project/.stack-work/install/x86_64-osx/lts-11.16/8.2.2/doc/call-haskell-from-anything-1.1.0.0 --haddockdir=/Users/williamrusnack/.stack/global-project/.stack-work/install/x86_64-osx/lts-11.16/8.2.2/doc/call-haskell-from-anything-1.1.0.0 --dependency=base=base-4.10.1.0 --dependency=bytestring=bytestring-0.10.8.2 --dependency=data-msgpack=data-msgpack-0.0.11-43aoBLbL2vlIA79OyvtcA5 --dependency=mtl=mtl-2.2.2-8XubxMJDT8QLsstvlNotkc --dependency=storable-endian=storable-endian-0.2.6-2dQ25FxlT5r2sRQGyd1Jot --dependency=template-haskell=template-haskell-2.12.0.0
    Process exited with code: ExitFailure 127
    Logs have been written to: /Users/williamrusnack/.stack/global-project/.stack-work/logs/call-haskell-from-anything-1.1.0.0.log

    [1 of 2] Compiling Main             ( /private/var/folders/zj/p9mj9djj3c3b4vjw5yzq1ckr0000gn/T/stack90413/call-haskell-from-anything-1.1.0.0/Setup.hs, /private/var/folders/zj/p9mj9djj3c3b4vjw5yzq1ckr0000gn/T/stack90413/call-haskell-from-anything-1.1.0.0/.stack-work/dist/x86_64-osx/Cabal-2.0.1.0/setup/Main.o )
    [2 of 2] Compiling StackSetupShim   ( /Users/williamrusnack/.stack/setup-exe-src/setup-shim-mPHDZzAJ.hs, /private/var/folders/zj/p9mj9djj3c3b4vjw5yzq1ckr0000gn/T/stack90413/call-haskell-from-anything-1.1.0.0/.stack-work/dist/x86_64-osx/Cabal-2.0.1.0/setup/StackSetupShim.o )
    Linking /private/var/folders/zj/p9mj9djj3c3b4vjw5yzq1ckr0000gn/T/stack90413/call-haskell-from-anything-1.1.0.0/.stack-work/dist/x86_64-osx/Cabal-2.0.1.0/setup/setup ...
    Configuring call-haskell-from-anything-1.1.0.0...
    ./configure: line 4: python2: command not found

Operating system: osx 10.11.6
stack --version 1.7.1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.