| ... | @@ -132,6 +132,10 @@ pub const LinuxDynLib = struct { | ... | @@ -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 | pub fn close(self: *LinuxDynLib) void { | 139 | pub fn close(self: *LinuxDynLib) void { |
| 136 | os.munmap(self.memory); | 140 | os.munmap(self.memory); |
| 137 | os.close(self.fd); | 141 | os.close(self.fd); |
| ... | @@ -148,8 +152,6 @@ pub const LinuxDynLib = struct { | ... | @@ -148,8 +152,6 @@ pub const LinuxDynLib = struct { |
| 148 | }; | 152 | }; |
| 149 | | 153 | |
| 150 | pub const ElfLib = struct { | 154 | pub const ElfLib = struct { |
| 151 | strings: [*:0]u8, | | |
| 152 | | | |
| 153 | pub const Error = error{ | 155 | pub const Error = error{ |
| 154 | NotElfFile, | 156 | NotElfFile, |
| 155 | NotDynamicLibrary, | 157 | NotDynamicLibrary, |
| ... | @@ -160,7 +162,7 @@ pub const ElfLib = struct { | ... | @@ -160,7 +162,7 @@ pub const ElfLib = struct { |
| 160 | ElfHashTableNotFound, | 162 | ElfHashTableNotFound, |
| 161 | }; | 163 | }; |
| 162 | | 164 | |
| 163 | strings: [*]u8, | 165 | strings: [*:0]u8, |
| 164 | syms: [*]elf.Sym, | 166 | syms: [*]elf.Sym, |
| 165 | hashtab: [*]os.Elf_Symndx, | 167 | hashtab: [*]os.Elf_Symndx, |
| 166 | versym: ?[*]u16, | 168 | versym: ?[*]u16, |
| ... | @@ -270,9 +272,18 @@ pub const WindowsDynLib = struct { | ... | @@ -270,9 +272,18 @@ pub const WindowsDynLib = struct { |
| 270 | dll: windows.HMODULE, | 272 | dll: windows.HMODULE, |
| 271 | | 273 | |
| 272 | pub fn open(path: []const u8) !WindowsDynLib { | 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 | return WindowsDynLib{ | 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,20 +292,13 @@ pub const WindowsDynLib = struct { |
| 281 | self.* = undefined; | 292 | self.* = undefined; |
| 282 | } | 293 | } |
| 283 | | 294 | |
| 284 | pub fn lookupC(self: *WindowsDynLib, comptime T: type, name: [*:0]const u8) ?T { | 295 | pub fn lookup(self: *DlDynlib, comptime T: type, name: [:0]const u8) ?T { |
| 285 | if (windows.kernel32.GetProcAddress(self.dll, name)) |addr| { | 296 | if (windows.kernel32.GetProcAddress(self.dll, name.ptr)) |addr| { |
| 286 | return @ptrCast(T, addr); | 297 | return @ptrCast(T, addr); |
| 287 | } else { | 298 | } else { |
| 288 | return null; | 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 | pub const DlDynlib = struct { | 304 | pub const DlDynlib = struct { |
| ... | @@ -303,12 +307,13 @@ pub const DlDynlib = struct { | ... | @@ -303,12 +307,13 @@ pub const DlDynlib = struct { |
| 303 | handle: *c_void, | 307 | handle: *c_void, |
| 304 | | 308 | |
| 305 | pub fn open(path: []const u8) !DlDynlib { | 309 | pub fn open(path: []const u8) !DlDynlib { |
| 306 | if (!builtin.link_libc and !os.darwin.is_the_target) { | 310 | const path_c = try os.toPosixPath(path); |
| 307 | @compileError("DlDynlib requires libc"); | 311 | return openC(&path_c); |
| 308 | } | 312 | } |
| 309 | | 313 | |
| | 314 | pub fn openC(path_c: [*:0]const u8) !DlDynlib { |
| 310 | return DlDynlib{ | 315 | return DlDynlib{ |
| 311 | .handle = system.dlopen(path.ptr, system.RTLD_LAZY) orelse { | 316 | .handle = system.dlopen(path_c, system.RTLD_LAZY) orelse { |
| 312 | return error.FileNotFound; | 317 | return error.FileNotFound; |
| 313 | }, | 318 | }, |
| 314 | }; | 319 | }; |
| ... | @@ -319,20 +324,15 @@ pub const DlDynlib = struct { | ... | @@ -319,20 +324,15 @@ pub const DlDynlib = struct { |
| 319 | self.* = undefined; | 324 | self.* = undefined; |
| 320 | } | 325 | } |
| 321 | | 326 | |
| 322 | pub fn lookupC(self: *DlDynlib, comptime T: type, name: [*:0]const u8) ?T { | 327 | pub fn lookup(self: *DlDynlib, comptime T: type, name: [*:0]const u8) ?T { |
| 323 | if (system.dlsym(self.handle, name)) |symbol| { | 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 | return @ptrCast(T, symbol); | 331 | return @ptrCast(T, symbol); |
| 325 | } else { | 332 | } else { |
| 326 | return null; | 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 | test "dynamic_library" { | 338 | test "dynamic_library" { |
| ... | @@ -340,7 +340,7 @@ test "dynamic_library" { | ... | @@ -340,7 +340,7 @@ test "dynamic_library" { |
| 340 | .linux => "invalid_so.so", | 340 | .linux => "invalid_so.so", |
| 341 | .windows => "invalid_dll.dll", | 341 | .windows => "invalid_dll.dll", |
| 342 | .macosx, .tvos, .watchos, .ios => "invalid_dylib.dylib", | 342 | .macosx, .tvos, .watchos, .ios => "invalid_dylib.dylib", |
| 343 | else => return, | 343 | else => return error.SkipZigTest, |
| 344 | }; | 344 | }; |
| 345 | | 345 | |
| 346 | const dynlib = DynLib.open(libname) catch |err| { | 346 | const dynlib = DynLib.open(libname) catch |err| { |