Best way to handle custom C-bindings in Shards

I’m currently working on a shard with some custom .c files and I wondered how should I handle the bindings in Crystal. In the examples that I have found Crystal uses the linker directly on object files. Is there any way to compile the .c files during the installation of the shard?


Checkout the postinstall hook within shards/shard.yml.adoc at master · crystal-lang/shards · GitHub.


Here’s a shard doing that, in case you need a real world example: myhtml/shard.yml at a4d1e8b8956731588752bc6e5164139cf8f29acb · kostya/myhtml · GitHub


I don’t think this is usually a good idea though. Distribution of source code and binary libraries should be separated. There are lots of issues with trying to build stuff automatically. You need a working toolchain for building the library. It won’t work if you’re cross compiling. Building the library from source is not as efficient as re-using a pre-built binary. …

1 Like

I don’t know if it’s the best way or not, but Ruby works exactly like that and I can’t remember people complaining about the way it works.

What alternative do you suggest?

1 Like

I was already once bitten by this. there is a youtube shard (GitHub - iv-org/invidious: Invidious is an alternative front-end to YouTube) that i wanted to run on a Raspberry pi, only to notice that it ships a binary library that of course does not work on ARM.

So, yes, mixing code and binary in a repo is always a bad idea.
I think a fresh language should have protability as an ideal. No need to repeat the errors of the past.


I don’t feel able to judge what’s the better way (or even the right way) and what isn’t, as both ways have their ups and downs. But I would disagree that this is how it works in Ruby. If Ruby gems come with C code, they always compiled the C stuff during gem install

Thinking about it - is it possible that this behaviour is depending on the platform? I think to remember that on Windows the gems came indeed already precompiled. But I have never seen it like that for OSX or Linux.

If Ruby gems come with C code, they always compiled the C stuff during gem install

That’s what happens with Crystal too. So how is that different than Ruby?

Oh my bad, sorry.
In that case I obviously misunderstood you (or misunderstood the rest of this topic regarding how things happen in Crystal).

There’s a difference between

  1. A gem/shard that has parts of its implementation written in C.
  2. A gem/shard that provides bindings to an existing C library.

Case 1 is typical in Ruby for performance reasons. But it’s pretty uncommon in Crystal because you can write performant implementations directly in Crystal. The C code is an integral element of this specific project, and when it is installed, it needs to build its own C library.

Case 2 happens in both Ruby and Crystal for the purpose of reusing existing libraries. Here, the C code comes from somewhere else, and it’s usually easy to acquire pre-build binaries for the respective library. So there’s no need to worry about building it from the gem/shard itself.
Instead, you can use whatever packaging mechanism that your system provides for installing binary packages.


Is Crystal performant enough to consider porting my C code to Crystal? I’m working mainly on random number generation

I don’t know how it’s regarding your specific use case (random number generation),
but of the (very limited) things I have done with Crystal, the speed was incredible and would not justify to deal with any C code.


Crystal’s performance is on par with C for a lot of things. If your code is exclusively CPU-bound (rather than, say, talking over a network) you might notice Crystal being slightly slower, but not radically so. If you’re doing network I/O, the gap closes significantly.

As with all performance comparisons, though, the best way to answer the question is to try porting it over. Otherwise, the best we can do is speculate.