It is possible to load a library at runtime without linking it at compile time statically nor dynamically. The POSIX functions that allow us to do this are dlopen(), dlsym(), dlerror() and dlclose() (these functions are found under dlfcn.h). The zig equivalent functions are found under std.DynLib. The purposes of why one might want to do this is to load plugins or to load optional features. So lets write a small "plugin" that adds two numbers.
Note: At the time of writing, latest stable version of zig is 0.16.0 and windows implementation for this functionality is not present in std lib. Because of this we are going with Linux.
// plugin__add.zig
export fn my_add(num1: i32, num2: i32) callconv(.c) i32 {
return num1 + num2;
}
Lets build dynamic library using zig build-lib -dynamic -O ReleaseSafe plugin__add.zig. This will create libplugin__add.so. Now lets write main code.
// plugin__main.zig
const std = @import("std");
pub fn main(init: std.process.Init) !void {
// setting up stdout writer
var buffer: [1024]u8 = undefined;
var file_writer = std.Io.File.Writer.init(.stdout(), init.io, &buffer);
var stdout_writer = &file_writer.interface;
var lib = try std.DynLib.open("./libplugin__add.so");
defer lib.close();
const AddFn = *const fn (num1: i32, num2: i32) callconv(.c) i32;
const my_add = lib.inner.lookup(AddFn, "my_add").?;
try stdout_writer.print("{}+{}={}\n", .{ 5, 6, my_add(5, 6) });
try stdout_writer.flush();
}
Lets build our main code using zig build-exe -O ReleaseSafe plugin__main.zig. This will create plugin__main executable which will print 5+6=11.
Thanks for reading. To be continued.
Top comments (0)