cImport don't check `#includes`? typedef didn't appear after cImport

Hi, I’m working on OBS multichat plugin and trying to write it in Zig. While I’ve tried to implement simple video source, I found this:

src/multichat_source.zig:5:20: error: C import failed
const obs_source = @cImport(@cInclude("obs/obs-source.h"));
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
referenced by:
    multichat_source_info: src/multichat_source.zig:9:35
    multichat_obs_source: src/main.zig:26:46
    remaining reference traces hidden; use '-freference-trace' to see all reference traces
/usr/include/obs/obs.h:1086:9: error: unknown type name 'obs_source_enum_proc_t'
        obs_source_enum_proc_t enum_callback,
        ^
/usr/include/obs/obs.h:1091:6: error: unknown type name 'obs_source_enum_proc_t'
     obs_source_enum_proc_t enum_callback,
     ^
/usr/include/obs/obs.h:1095:11: error: unknown type name 'obs_source_enum_proc_t'
          obs_source_enum_proc_t enum_callback,
          ^
/usr/include/obs/obs.h:1169:9: error: unknown type name 'obs_source_enum_proc_t'
        obs_source_enum_proc_t callback,

Then I’ve checked obs/obs-source.h, it has:

typedef void (*obs_source_enum_proc_t)(obs_source_t *parent,
				       obs_source_t *child, void *param);

obs/obs.h includes obs-source.h at the beginning, while errors appear from 1086 line.

Is there a way to fix this?
Part of my build.zig

const lib = b.addSharedLibrary(.{
    .name = "OBS-Studio-chat-plugin",
    .root_source_file = .{ .path = "src/main.zig" },
    .target = target,
    .optimize = optimize,
    .version = .{
        .major = 0,
        .minor = 0,
        .patch = 1,
    },
});

lib.linkLibC();
lib.linkSystemLibrary("libobs");
b.installArtifact(lib);

src/multichat_source.zig:

const std = @import("std");

const obs = @cImport(@cInclude("obs/obs.h"));
const obs_module = @cImport(@cInclude("obs/obs-module.h"));
const obs_source = @cImport(@cInclude("obs/obs-source.h"));
const obs_graphics = @cImport(@cInclude("obs/graphics/graphics.h"));
const obs_data = @cImport(@cInclude("obs/obs-data.h"));

pub const multichat_source_info = obs_source.obs_source_info {
    "multichat_source",                                 // id
    obs_source.obs_source_type.OBS_SOURCE_TYPE_INPUT,   // type
    obs_source.OBS_SOURCE_VIDEO,                        // output_flags
    get_name,                                           // get_name
    create,                                             // create
    destroy,                                            // destroy
    update,                                             // update
    video_render,                                       // video_render
    null,                                               // get_width
    null                                                // get_height
};

fn get_name(unused: *void) [*]u8 {
    _ = unused;
    return obs_module.obs_module_text("OBS Multi Chat");
}

fn create(settings: *obs_data.obs_data_t, source: *obs.obs_source_t) *anyopaque {
    const context: *multichat_source = std.heap.Alloc(multichat_source){
        .allocator = std.heap.page_allocator,
        .source = source
    };
    _ = settings;
    return context;
}

fn destroy(data: *anyopaque) void {
    _ = data;
}

fn update(data: *anyopaque, settings: *obs_data.obs_data_t) void {
    _ = data;
    _ = settings;
}

fn video_render(data: *anyopaque, effect: *obs_graphics.gs_effect_t) void {
    _ = data;
    _ = effect;
}

const multichat_source = struct {
    allocator: std.mem.Allocator,
    source: *obs.obs_source_t,
};

Few fn placeholders for testing

May be I didn’t see something?
OBS Plugin API docs

One thing to try here is to import them under one @cImport call. I’ve had this issue before and that helped - you can do mulitiple @cInclude calls per @cImport.

2 Likes

Thx, that works! I’ve tried different things, but solution was so simple :melting_face:

1 Like

I’ll also add an example:

const obs = @cImport({
    @cInclude("obs/obs.h");
    @cInclude("obs/obs-source.h");
    @cInclude("obs/graphics/graphics.h");
    @cInclude("obs/obs-data.h");
});

The order of @cInclude is important

2 Likes