Using C libraries - Code review

Hi,
I am playing around with calling routines from a C library (FFTW3) and wrote the following code that does precisely what it should. The fftw_plan_dft_1d needs the address of the input and output array. II achieve this by passing a reference to the 0-th element (&(data.items[0])). The compiler goes with it, but it feels a little bit dirty. Is there a cleaner way? And are there more things I could improve? (Still relatively new to zig)
Thank you for your Help.

The code:
main.zig:

const std = @import("std");
const stdout = std.io.getStdOut().writer();
const fftw = @cImport(@cInclude("fftw3.h"));

const ArrayList = std.ArrayList;
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();

fn print_array(array: ArrayList(fftw.fftw_complex)) !void {
    for (array.items) |r| {
        try stdout.print("({0d:5.2}, {1d:5.2}) ", .{ r[0], r[1] }); 
    }   
    try stdout.print("\n", .{});
}

pub fn main() !void {
    const size = 8;

    var data = try ArrayList(fftw.fftw_complex).initCapacity(allocator, size);
    defer data.deinit();
    var ftdata = try ArrayList(fftw.fftw_complex).initCapacity(allocator, size);
    defer ftdata.deinit();

    for (0..(size / 2)) |_| {
        _ = try data.append(.{ 1.0, 0.0 }); 
        _ = try ftdata.append(.{ 0.0, 0.0 }); 
    }   
    for ((size / 2)..size) |_| {
        _ = try data.append(.{ 0.0, 0.0 }); 
        _ = try ftdata.append(.{ 0.0, 0.0 }); 
    }   
    try print_array(data);
    try print_array(ftdata);
    try stdout.print("\n", .{});

    const plan_fw = fftw.fftw_plan_dft_1d(size, &(data.items[0]), &(ftdata.items[0]), fftw.FFTW_FORWARD, fftw.FFTW_ESTIMATE);
    defer fftw.fftw_destroy_plan(plan_fw);
    fftw.fftw_execute(plan_fw);
    try print_array(data);
    try print_array(ftdata);
    try stdout.print("\n", .{});

    for (data.items) |*r| {
        r.* = .{ 0.0, 0.0 };
    }   
    try print_array(data);
    try print_array(ftdata);
    try stdout.print("\n", .{});

    const plan_bw = fftw.fftw_plan_dft_1d(size, &(ftdata.items[0]), &(data.items[0]), fftw.FFTW_BACKWARD, fftw.FFTW_ESTIMATE);
    defer fftw.fftw_destroy_plan(plan_bw);
    fftw.fftw_execute(plan_bw);
    try print_array(data);
    try print_array(ftdata);
}

build.zig:

const std = @import("std");

pub fn build(b: *std.Build) void {
    const exe = b.addExecutable(.{
        .name = "fft.x",
        .root_source_file = b.path("main.zig"),
        .target = b.host,
    }); 
    exe.linkSystemLibrary2("fftw3", .{ .preferred_link_mode = .static }); 
    exe.linkLibC();
    b.installArtifact(exe);

    const run_exe = b.addRunArtifact(exe);
    const run_step = b.step("run", "Run the application");
    run_step.dependOn(&run_exe.step);
}

You can use data.items.ptr.

2 Likes