Hi all, I am trying to execute a function that gets linked from C file that gets linked into the executable in build.zig. I was able to get it to work for linux but i am not sure why the recommended way for windows is not working for me. Here is the code i am using and let me know what i am doing wrong please.
src/main.c
void add(int a, int b) {
printf("Add a %d\n", a + b);
}
build.zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe_mod = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const add = b.addSharedLibrary(.{
.name = "add",
.target = target,
.optimize = optimize,
.link_libc = true,
});
add.addCSourceFiles(.{ .root = b.path("src/"), .files = &.{
"main.c",
} });
const exe = b.addExecutable(.{
.name = "dynamic_dispatch",
.root_module = exe_mod,
});
exe.linkLibC();
exe.linkLibrary(add);
b.installArtifact(exe);
b.installArtifact(add);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
and my src/main.zig
const Handle = if (builtin.os.tag == .windows) c.HMODULE else ?*anyopaque;
var main_program_handle: Handle = null;
pub fn initDynamicSymbolHandling() void {
if (builtin.os.tag == .windows) {
main_program_handle = c.GetModuleHandleA(null);
} else {
main_program_handle = c.dlopen(null, c.RTLD_LAZY);
}
if (main_program_handle == null) {
std.log.err("No handle of the main program\n", .{});
}
}
pub fn callCFunction() ?*const fn (c_int, c_int) callconv(.c) void {
const method = "add";
if (builtin.os.tag == .windows) {
const proc = c.GetProcAddress(main_program_handle, method.ptr);
if (proc == null) {
std.log.err("No Proc .{any}\n", .{proc});
return null;
}
return @ptrFromInt(@intFromPtr(proc));
} else {
const proc = c.dlsym(main_program_handle, method.ptr);
std.debug.print("Proc is {any}\n", .{proc});
return @ptrFromInt(@intFromPtr(c.dlsym(main_program_handle, method.ptr)));
}
}
pub fn main() !void {
initDynamicSymbolHandling();
const add = callCFunction();
if (add) |proc| {
proc(1, 2);
}
std.debug.print("All your {s} are belong to us.\n", .{"codebase"});
}
const std = @import("std");
const builtin = @import("builtin");
const c = if (builtin.os.tag == .windows) @cImport({
@cInclude("windows.h");
}) else @cImport({
@cInclude("dlfcn.h");
});
Appreciate any kind of ur help.
I would also like to state that if i specify the dll file by name, (based on recommendations i find online) the execution works for windows too, but i do not like the fact that i have to specify the âdllâ file by its name.
if (builtin.os.tag == .windows) {
const libname = "add.dll";
const handle = c.LoadLibraryA(libname.ptr);
if (handle == null) {
std.debug.print("Failed Loading DLL: {s}\n", .{libname});
return null;
}
const symbol_name = "add";
const add_fn_ptr = c.GetProcAddress(handle, symbol_name.ptr);
if (add_fn_ptr == null) {
std.debug.print("Symbol {s}\n", .{symbol_name});
return null;
}
return @ptrFromInt(@intFromPtr(add_fn_ptr));
}
Thanks