| ... | ... | @@ -132,6 +132,10 @@ pub const LinuxDynLib = struct { |
| 132 | 132 | }; |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | pub fn openC(path_c: [*:0]const u8) !LinuxDynLib { |
| 136 | return open(mem.toSlice(u8, path_c)); |
| 137 | } |
| 138 | |
| 135 | 139 | pub fn close(self: *LinuxDynLib) void { |
| 136 | 140 | os.munmap(self.memory); |
| 137 | 141 | os.close(self.fd); |
| ... | ... | @@ -148,8 +152,6 @@ pub const LinuxDynLib = struct { |
| 148 | 152 | }; |
| 149 | 153 | |
| 150 | 154 | pub const ElfLib = struct { |
| 151 | | strings: [*:0]u8, |
| 152 | | |
| 153 | 155 | pub const Error = error{ |
| 154 | 156 | NotElfFile, |
| 155 | 157 | NotDynamicLibrary, |
| ... | ... | @@ -160,7 +162,7 @@ pub const ElfLib = struct { |
| 160 | 162 | ElfHashTableNotFound, |
| 161 | 163 | }; |
| 162 | 164 | |
| 163 | | strings: [*]u8, |
| 165 | strings: [*:0]u8, |
| 164 | 166 | syms: [*]elf.Sym, |
| 165 | 167 | hashtab: [*]os.Elf_Symndx, |
| 166 | 168 | versym: ?[*]u16, |
| ... | ... | @@ -270,9 +272,18 @@ pub const WindowsDynLib = struct { |
| 270 | 272 | dll: windows.HMODULE, |
| 271 | 273 | |
| 272 | 274 | pub fn open(path: []const u8) !WindowsDynLib { |
| 273 | | const wpath = try windows.sliceToPrefixedFileW(path); |
| 275 | const path_w = try windows.sliceToPrefixedFileW(path); |
| 276 | return openW(&path_w); |
| 277 | } |
| 278 | |
| 279 | pub fn openC(path_c: [*:0]const u8) !WindowsDynLib { |
| 280 | const path_w = try windows.cStrToPrefixedFileW(path); |
| 281 | return openW(&path_w); |
| 282 | } |
| 283 | |
| 284 | pub fn openW(path_w: [*:0]const u16) !WindowsDynLib { |
| 274 | 285 | return WindowsDynLib{ |
| 275 | | .dll = try windows.LoadLibraryW(&wpath), |
| 286 | .dll = try windows.LoadLibraryW(path_w), |
| 276 | 287 | }; |
| 277 | 288 | } |
| 278 | 289 | |
| ... | ... | @@ -281,20 +292,13 @@ pub const WindowsDynLib = struct { |
| 281 | 292 | self.* = undefined; |
| 282 | 293 | } |
| 283 | 294 | |
| 284 | | pub fn lookupC(self: *WindowsDynLib, comptime T: type, name: [*:0]const u8) ?T { |
| 285 | | if (windows.kernel32.GetProcAddress(self.dll, name)) |addr| { |
| 295 | pub fn lookup(self: *DlDynlib, comptime T: type, name: [:0]const u8) ?T { |
| 296 | if (windows.kernel32.GetProcAddress(self.dll, name.ptr)) |addr| { |
| 286 | 297 | return @ptrCast(T, addr); |
| 287 | 298 | } else { |
| 288 | 299 | return null; |
| 289 | 300 | } |
| 290 | 301 | } |
| 291 | | |
| 292 | | pub fn lookup(self: *DlDynlib, comptime T: type, comptime max_name_len: usize, name: []const u8) ?T { |
| 293 | | const c_name: [max_name_len]u8 = undefined; |
| 294 | | mem.copy(&c_name, name); |
| 295 | | c_name[name.len] = 0; |
| 296 | | return self.lookupC(T, &c_name); |
| 297 | | } |
| 298 | 302 | }; |
| 299 | 303 | |
| 300 | 304 | pub const DlDynlib = struct { |
| ... | ... | @@ -303,12 +307,13 @@ pub const DlDynlib = struct { |
| 303 | 307 | handle: *c_void, |
| 304 | 308 | |
| 305 | 309 | pub fn open(path: []const u8) !DlDynlib { |
| 306 | | if (!builtin.link_libc and !os.darwin.is_the_target) { |
| 307 | | @compileError("DlDynlib requires libc"); |
| 308 | | } |
| 310 | const path_c = try os.toPosixPath(path); |
| 311 | return openC(&path_c); |
| 312 | } |
| 309 | 313 | |
| 314 | pub fn openC(path_c: [*:0]const u8) !DlDynlib { |
| 310 | 315 | return DlDynlib{ |
| 311 | | .handle = system.dlopen(path.ptr, system.RTLD_LAZY) orelse { |
| 316 | .handle = system.dlopen(path_c, system.RTLD_LAZY) orelse { |
| 312 | 317 | return error.FileNotFound; |
| 313 | 318 | }, |
| 314 | 319 | }; |
| ... | ... | @@ -319,20 +324,15 @@ pub const DlDynlib = struct { |
| 319 | 324 | self.* = undefined; |
| 320 | 325 | } |
| 321 | 326 | |
| 322 | | pub fn lookupC(self: *DlDynlib, comptime T: type, name: [*:0]const u8) ?T { |
| 323 | | if (system.dlsym(self.handle, name)) |symbol| { |
| 327 | pub fn lookup(self: *DlDynlib, comptime T: type, name: [*:0]const u8) ?T { |
| 328 | // dlsym (and other dl-functions) secretly take shadow parameter - return address on stack |
| 329 | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66826 |
| 330 | if (@call(.{ .modifier = .never_tail }, system.dlsym, .{ self.handle, name.ptr })) |symbol| { |
| 324 | 331 | return @ptrCast(T, symbol); |
| 325 | 332 | } else { |
| 326 | 333 | return null; |
| 327 | 334 | } |
| 328 | 335 | } |
| 329 | | |
| 330 | | pub fn lookup(self: *DlDynlib, comptime T: type, comptime max_name_len: usize, name: []const u8) ?T { |
| 331 | | const c_name: [max_name_len]u8 = undefined; |
| 332 | | mem.copy(&c_name, name); |
| 333 | | c_name[name.len] = 0; |
| 334 | | return self.lookupC(T, &c_name); |
| 335 | | } |
| 336 | 336 | }; |
| 337 | 337 | |
| 338 | 338 | test "dynamic_library" { |
| ... | ... | @@ -340,7 +340,7 @@ test "dynamic_library" { |
| 340 | 340 | .linux => "invalid_so.so", |
| 341 | 341 | .windows => "invalid_dll.dll", |
| 342 | 342 | .macosx, .tvos, .watchos, .ios => "invalid_dylib.dylib", |
| 343 | | else => return, |
| 343 | else => return error.SkipZigTest, |
| 344 | 344 | }; |
| 345 | 345 | |
| 346 | 346 | const dynlib = DynLib.open(libname) catch |err| { |