{"id":13702048,"url":"https://github.com/minimapletinytools/haskell-ffi-cabal-foreign-library-examples","last_synced_at":"2025-03-25T14:32:22.306Z","repository":{"id":136719558,"uuid":"178622122","full_name":"minimapletinytools/haskell-ffi-cabal-foreign-library-examples","owner":"minimapletinytools","description":"Example project of using cabal 2.0`s foreign-library feature to build a haskell library that lets you call haskell code from C/C++.","archived":false,"fork":false,"pushed_at":"2020-02-22T01:30:23.000Z","size":22,"stargazers_count":16,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-17T04:02:35.201Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/minimapletinytools.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-03-30T23:31:50.000Z","updated_at":"2025-03-06T02:36:43.000Z","dependencies_parsed_at":"2024-01-14T19:29:04.755Z","dependency_job_id":null,"html_url":"https://github.com/minimapletinytools/haskell-ffi-cabal-foreign-library-examples","commit_stats":null,"previous_names":["minimapletinytools/haskell-ffi-cabal-foreign-library-examples"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minimapletinytools%2Fhaskell-ffi-cabal-foreign-library-examples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minimapletinytools%2Fhaskell-ffi-cabal-foreign-library-examples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minimapletinytools%2Fhaskell-ffi-cabal-foreign-library-examples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minimapletinytools%2Fhaskell-ffi-cabal-foreign-library-examples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/minimapletinytools","download_url":"https://codeload.github.com/minimapletinytools/haskell-ffi-cabal-foreign-library-examples/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245090871,"owners_count":20559298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T21:00:30.442Z","updated_at":"2025-03-25T14:32:22.054Z","avatar_url":"https://github.com/minimapletinytools.png","language":"Haskell","funding_links":[],"categories":["Components"],"sub_categories":[],"readme":"# haskell-ffi-cabal-foreign-library-examples\n\nThis repository contains a Cabal 2.0 project showing how to build a haskell library to use in c/c++ using the new [foreign-library](https://cabal.readthedocs.io/en/latest/developing-packages.html#foreign-libraries) feature. The `foreign-library` feature greatly simplifies the process of creating haskell libraries for use by other languages.\n\nThe `lens` and `deepseq` packages are included mainly as a test case for dependencies. The example contains code that is intended to test features _I_ need for my own projects, in particular [AnimalClub](https://github.com/pdlla/animalclub). I would love to merge a PR including more relevant examples 😘.\n\n## Usage\n\n`make run`\n\nIt was tested on Mac and Linux (Ubuntu 19.04 with cabal 2.4 and ghc 8.6.5).\n\n## Walkthrough\n\n`potato.cabal` defines our module using `foreign-library`\n\n```\nforeign-library potato\n  type:                native-shared\n\n  if os(Windows)\n    options: standalone\n    mod-def-file: PotatoLib.def\n\n  other-modules:       Potato\n  build-depends:\n    base ^\u003e=4.12.0.0\n    , lens == 4.*\n    , deepseq == 1.4.*\n  hs-source-dirs:      src\n  c-sources:           csrc/potato.cpp\n  default-language:    Haskell2010\n```\n\nNote, to support stack pipeline, this is done using the `verbatim` field in `package.yaml`.\n\nPlease see [cabal docs](https://cabal.readthedocs.io/en/latest/developing-packages.html#foreign-libraries) for a more thorough description explaining the meaning of each field. The important detail here is\n\n```\nc-sources:           csrc/potato.cpp\n```\n\nwhich points to a file that `cabal build` will build for us (and handle all linker/include issues for us). In this case, we wrap all exported methods from our 🥔 Haskell module and from ghc's `HsFFI.h` inside of helper functions. Only `potato.h` needs to be included by the user. In this manner, we are building a 🥔 *c++* library that calls our 🥔 haskell library. If you don't wish to wrap the functionality, you can simply leave `potato.cpp` empty and call the exported methods from our 🥔 haskell library directly. In this case, you'll need to include `Potato_stub.h` which is generated by `cabal build` and likely `HsFFI.h` when you use the library.\n\n`void potatoInit(void);` and `void potatoExit(void);` simply wrap `hs_init` and `hs_exit` which start and stop the haskell runtime respectively. `void test()` calls all the functions in our 🥔 haskell module.\n\nThe `capp/` folder contains our cpp source that will call code from our haskell `potato` module. The makefile builds the cpp app using `g++` with the needed flags. Note that it expects the hs library files to be in this directory to work.\n\n```\ng++ -g -Wall potatomain.cpp -o $@ \\\n-I../csrc \\\n-lpotato \\\n-L./\n```\n\nAs mentioned earlier, if you want your `capp/potatomain.cpp` to use methods from the Haskell library directly instead of calling through `csrc/potato.h`, then you will need to add the flags `-I../dist/build/potato/potato-tmp` for `Potato_stub.h` and something like `-I/usr/local/lib/ghc-8.4.4/include/` for `HsFFI.h`. I don't recommend this since it's unclear to me where to fetch these dependencies from in a build pipeline.\n\nFinally, the makefile in the root directory runs `stack build` and copies the compiled library into the `capp` folder. Then it calls `make` inside of `capp`. `make run` runs the app it compiled in `capp`.\n\n## Cabal\n`make usingcabal` will do the same thing with cabal instead of stack. It uses a different .cabal file but you could probably make it work with the stack generated one too.\n\n## THX\nI used [this guide](https://ro-che.info/articles/2017-07-26-haskell-library-in-c-project) as a starting point which includes links to many other resources I found helpful so I won't list them here. The guide contains a script for gathering the scattered libraries but I didn't seem to need it here. As far as I can tell, Cabal 2.0 will package everything that's needed into a single shared library.\n\nEnjoy!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminimapletinytools%2Fhaskell-ffi-cabal-foreign-library-examples","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fminimapletinytools%2Fhaskell-ffi-cabal-foreign-library-examples","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminimapletinytools%2Fhaskell-ffi-cabal-foreign-library-examples/lists"}