authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-10 12:28:28-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-10 12:28:28-05:00
logfd6b7b160d1fddf967177cf26704908aa7bf5f12
tree438d5732638163b907968ac1f443797d42ad2c3d
parent29fd727b79682a0f3e8ad7340cf86db989b9109e
signature Commit is signed but in an unrecognized format.

improve dynamic library API


6 files changed, 44 insertions(+), 41 deletions(-)

lib/std/c.zig+4
...@@ -226,3 +226,7 @@ pub extern "c" fn pthread_cond_destroy(cond: *pthread_cond_t) c_int;...@@ -226,3 +226,7 @@ pub extern "c" fn pthread_cond_destroy(cond: *pthread_cond_t) c_int;
226226
227pub const pthread_t = *@OpaqueType();227pub const pthread_t = *@OpaqueType();
228pub const FILE = @OpaqueType();228pub const FILE = @OpaqueType();
229
230pub extern "c" fn dlopen(path: [*:0]const u8, mode: c_int) ?*c_void;
231pub extern "c" fn dlclose(handle: *c_void) c_int;
232pub extern "c" fn dlsym(handle: ?*c_void, symbol: [*:0]const u8) ?*c_void;
lib/std/c/darwin.zig-4
...@@ -128,7 +128,3 @@ pub const pthread_attr_t = extern struct {...@@ -128,7 +128,3 @@ pub const pthread_attr_t = extern struct {
128 __sig: c_long,128 __sig: c_long,
129 __opaque: [56]u8,129 __opaque: [56]u8,
130};130};
131
132pub extern "c" fn dlopen(path: [*]const u8, mode: c_int) ?*c_void;
133pub extern "c" fn dlclose(handle: *c_void) c_int;
134pub extern "c" fn dlsym(handle: ?*c_void, symbol: [*]const u8) ?*c_void;
lib/std/c/linux.zig+7
...@@ -98,3 +98,10 @@ const __SIZEOF_PTHREAD_MUTEX_T = if (builtin.os == .fuchsia) 40 else switch (bui...@@ -98,3 +98,10 @@ const __SIZEOF_PTHREAD_MUTEX_T = if (builtin.os == .fuchsia) 40 else switch (bui
98 },98 },
99 else => unreachable,99 else => unreachable,
100};100};
101
102pub const RTLD_LAZY = 1;
103pub const RTLD_NOW = 2;
104pub const RTLD_NOLOAD = 4;
105pub const RTLD_NODELETE = 4096;
106pub const RTLD_GLOBAL = 256;
107pub const RTLD_LOCAL = 0;
lib/std/dynamic_library.zig+28-28
...@@ -132,6 +132,10 @@ pub const LinuxDynLib = struct {...@@ -132,6 +132,10 @@ pub const LinuxDynLib = struct {
132 };132 };
133 }133 }
134134
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};
149153
150pub const ElfLib = struct {154pub 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 };
162164
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,
271273
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 }
278289
...@@ -281,20 +292,13 @@ pub const WindowsDynLib = struct {...@@ -281,20 +292,13 @@ pub const WindowsDynLib = struct {
281 self.* = undefined;292 self.* = undefined;
282 }293 }
283294
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};
299303
300pub const DlDynlib = struct {304pub 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,
304308
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 }
309313
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 }
321326
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};
337337
338test "dynamic_library" {338test "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 };
345345
346 const dynlib = DynLib.open(libname) catch |err| {346 const dynlib = DynLib.open(libname) catch |err| {
src/ir.cpp+1
...@@ -6561,6 +6561,7 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode...@@ -6561,6 +6561,7 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode
6561}6561}
65626562
6563static IrInstruction *ir_expr_wrap(IrBuilder *irb, Scope *scope, IrInstruction *inst, ResultLoc *result_loc) {6563static IrInstruction *ir_expr_wrap(IrBuilder *irb, Scope *scope, IrInstruction *inst, ResultLoc *result_loc) {
6564 if (inst == irb->codegen->invalid_instruction) return inst;
6564 ir_build_end_expr(irb, scope, inst->source_node, inst, result_loc);6565 ir_build_end_expr(irb, scope, inst->source_node, inst, result_loc);
6565 return inst;6566 return inst;
6566}6567}
test/standalone.zig+4-9
...@@ -1,6 +1,5 @@...@@ -1,6 +1,5 @@
1const std = @import("std");
1const tests = @import("tests.zig");2const tests = @import("tests.zig");
2const builtin = @import("builtin");
3const is_windows = builtin.os == builtin.Os.windows;
43
5pub fn addCases(cases: *tests.StandaloneContext) void {4pub fn addCases(cases: *tests.StandaloneContext) void {
6 cases.add("test/standalone/hello_world/hello.zig");5 cases.add("test/standalone/hello_world/hello.zig");
...@@ -19,14 +18,10 @@ pub fn addCases(cases: *tests.StandaloneContext) void {...@@ -19,14 +18,10 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
19 cases.addBuildFile("test/standalone/use_alias/build.zig");18 cases.addBuildFile("test/standalone/use_alias/build.zig");
20 cases.addBuildFile("test/standalone/brace_expansion/build.zig");19 cases.addBuildFile("test/standalone/brace_expansion/build.zig");
21 cases.addBuildFile("test/standalone/empty_env/build.zig");20 cases.addBuildFile("test/standalone/empty_env/build.zig");
22 switch (builtin.os) {21 if (std.Target.current.getOs() != .wasi) {
23 .linux, .windows, .macosx, .tvos, .watchos, .ios => {22 cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");
24 cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");
25 },
26 else => {},
27 }23 }
2824 if (std.Target.current.getArch() == .x86_64) { // TODO add C ABI support for other architectures
29 if (builtin.arch == builtin.Arch.x86_64) { // TODO add C ABI support for other architectures
30 cases.addBuildFile("test/stage1/c_abi/build.zig");25 cases.addBuildFile("test/stage1/c_abi/build.zig");
31 }26 }
32}27}