Learning C interop and low-level concepts coming from high-level language background

Hello, I’m coming from a programming background of mostly javascript and python. Recently I’ve started learning zig and have completed ziglings along with some small programs that interact with the gpio. Really enjoying it so far.

However there are a number code bases out there built in C that I would like to use and I am running into problems. I have successfully imported and used a simple single header and c file but I have had more difficulty integrating larger projects, even when I can compile them and run their examples.

I get errors from ld.lld (not sure what linking really means) and I don’t understand when in the build files I need to call addCSourceFiles versus just addIncludePath and I think this is due to my lack of experience with C.

So what should I be reading or doing to learn how to debug the zig - c connection? Hiredis is what I am currently trying to use from zig. Thank you!

Hello @Patrick
welcome to ziggit :slight_smile:


A community tutorial for using C from zig is the Working with C part of the zig guide.
You 'll also find useful the C part of the official zig reference, that describes various aspects of using C from zig.


The simplest way to use the library is to create a test.zig file with the following contents:

const redis = @cImport({
    @cInclude("hiredis.h");
});

pub fn main() void {
    const c = redis.redisConnect("127.0.0.1", 6379);
    defer redis.redisFree(c);
}

Then run it using the following command, replacing /path/to/* with the actual path to lib and h files:

zig run test.zig -lc -lhiredis -L/path/to/hiredis/lib -I/path/to/hiredis/include

where:

  • -l (lowercase L) means link to hiredis library (for linux libhiredis.so or libhiredis.a)
  • -L specifies in which folder are the libraries (path to libhiredis.*)
  • -I (uppercase i) specifies in which folder are the include files (path to hiredis.h)
2 Likes

Thank you so much I tried that out and it is working. I’ll be reading the other documentation soon but I have a few quick questions

  1. the run command was looking for libhiredis.so.1.2.1-dev.so. There is a #define HIREDIS_SONAME 1.2.1-dev in the hiredis header file. Is this what told zig to look for that path with that suffix?
  2. I’d like to cross compile this for arm architectures, I assume that this has to be done before hiredis is compiled. Is the strategy here to translate the Makefile into a build.zig?
  3. When I imported some simple C code I passed the .c file into the @cInclude function. Was this wrong? I was able to call out to the code from zig in that case.

No, it is the linker job to find the correct version.

That is one valid strategy. Another strategy is to use zig cc --target arm-linux as a c compiler (CC environment variable).

Most of the times it is not correct to include a .c file.
Normally you include .h files and you compile .c files into objects .o and then have the linker link all objects together.

1 Like