I encountered another strange issue. I’m loading a plugin as a dynamic library. I want to use the de-facto standard of providing a struct with all of the plugin functions. I’m getting a segmentation fault when trying to access them.
I am not really that picky on how the plugin_info struct is structured. I would be willing to even pass strings and then look them up. I have tried all kinds of ways but they all seem to result in segfaults.
Segmentation fault at address 0xd1d00
???:?:?: 0xd1d00 in ??? (???)
Unwind information for `???:0xd1d00` was not available, trace may be incomplete
/home/.../zig/lib/std/start.zig:616:37: 0x1035b6f in posixCallMainAndExit (xlatr)
const result = root.main() catch |err| {
^
/home/.../zig/lib/std/start.zig:240:5: 0x103575d in _start (xlatr)
asm volatile (switch (native_arch) {
^
I was able to lookup pluginAdd directly and verified that it works.
plugin_info is a comptime constant. .add is being set to the offset of pluginAdd from the beginning of the plugin module (0xd1d00 in your stack trace). But when the app tries to execute it, it thinks this is an offset to its own module. Calling functions directly (or, equivalently, storing pointers to functions at compile time) only works for functions inside the same module. The proper way to call functions across modules is by querying the function pointer. In Windows, you do that with GetProcAddress, I don’t know the equivalent in Zig’s std.
I’ve never seen this pattern of struct containing pointers. I think you’re overcomplicating this. The plugin needs to provide a function called add, so just name it add:
I looked at the source code for std.DynLib and, for most platforms, it just naively open the file. That’s not the most correct way of loading a module, because it skips rellocation, which is what would make these pointers become valid. libdl very likely does rellocation.
It looks like it. If the dynamic library doesn’t need relocation, it should work, but it would be quite fragile. Maybe this should warrant opening an issue.