Skip to content

Instantly share code, notes, and snippets.

@ramirez7
Last active July 21, 2022 14:31
Show Gist options
  • Select an option

  • Save ramirez7/5819bcb55e6ae00cc10043ac5e49a827 to your computer and use it in GitHub Desktop.

Select an option

Save ramirez7/5819bcb55e6ae00cc10043ac5e49a827 to your computer and use it in GitHub Desktop.

I've written a few FFI bindings that I use for my games:

  • cute-c2-hs and cute-sound-hs - These are bindings to single-header C libraries. The header itself is included in the git repo.
  • sdl-gpu-hs - This C/C++ library is not included in the repo. It is declared as a dependency via pkgconfig-depends in the .cabal file.

Some general tips I've picked up:

  • hsc2hs works great. It doesn't do much for you, but it give you a nice way to create safe bindings.
  • Try to make your binding as "literal" as possible. You will end up with a lot of boilerplate, but it' a good starting point.
    • You can embed any C function in Haskell with basically 0 overhead by using raw Ptrs and primitives.
    • After you have the verbatim C binding, you can build higher-level bindings. I like to make "simple" bindings next - they hide the Ptr allocation and poke-ing with a little unsafePerformIO and nothing more.
    • NOTE: If the library passes or returns structs by value, it isn't FFI-compatible. You'll have to write an adapter in C that takes a pointer and dereferences it to pass it by value. I usually have a c-bits directory for these adapters. The libraries above have examples.
  • Does bgfx have a proper C API? Or is it C++ only? If it's C++ only, you'll have to write a C wrapper that interops with it. And then you write Haskell bindings to that C wrapper.
  • In general, you're going to have to learn some C/C++ (and their build systems/compilation model). Or rather, expect to pick some stuff up along the way.
  • You'll also need to grok the C library as a C library before you use it in Haskell. I even wrote some C examples to help me learn.
  • I definitely recommend Nix if you're going to use C, but if you aren't interested in it, you'll have to figure out how to handle native dependencies for your computer.
    • Nix i a great C/C++ package manager, and it will auto-discover dependencies declared in .cabal files (such as pkgconfig-depends).
      • nixpkgs's Haskell build infrastructure works great.
      • I personally use haskell.nix because I cross-compile from NixOS to Windows. It handles Haskell x-compilation well. For C/C++, you will often have to do a little elbow grease to make it packaged for cross-compilation properly. I've spent a lot of time debugging C cross-compilation. But once it works, it's great!

I actually had bgfx in my notes as a library to consider trying out and binding, so it's cool that you're interested in trying it. If you do go after it, feel free to ask for help! I love working on this sort of stuff :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment