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;
226226
227227pub const pthread_t = *@OpaqueType();
228228pub 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 {
128128 __sig: c_long,
129129 __opaque: [56]u8,
130130};
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
9898 },
9999 else => unreachable,
100100};
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 {
132132 };
133133 }
134134
135 pub fn openC(path_c: [*:0]const u8) !LinuxDynLib {
136 return open(mem.toSlice(u8, path_c));
137 }
138
135139 pub fn close(self: *LinuxDynLib) void {
136140 os.munmap(self.memory);
137141 os.close(self.fd);
......@@ -148,8 +152,6 @@ pub const LinuxDynLib = struct {
148152};
149153
150154pub const ElfLib = struct {
151 strings: [*:0]u8,
152
153155 pub const Error = error{
154156 NotElfFile,
155157 NotDynamicLibrary,
......@@ -160,7 +162,7 @@ pub const ElfLib = struct {
160162 ElfHashTableNotFound,
161163 };
162164
163 strings: [*]u8,
165 strings: [*:0]u8,
164166 syms: [*]elf.Sym,
165167 hashtab: [*]os.Elf_Symndx,
166168 versym: ?[*]u16,
......@@ -270,9 +272,18 @@ pub const WindowsDynLib = struct {
270272 dll: windows.HMODULE,
271273
272274 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 {
274285 return WindowsDynLib{
275 .dll = try windows.LoadLibraryW(&wpath),
286 .dll = try windows.LoadLibraryW(path_w),
276287 };
277288 }
278289
......@@ -281,20 +292,13 @@ pub const WindowsDynLib = struct {
281292 self.* = undefined;
282293 }
283294
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| {
286297 return @ptrCast(T, addr);
287298 } else {
288299 return null;
289300 }
290301 }
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 }
298302};
299303
300304pub const DlDynlib = struct {
......@@ -303,12 +307,13 @@ pub const DlDynlib = struct {
303307 handle: *c_void,
304308
305309 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 }
309313
314 pub fn openC(path_c: [*:0]const u8) !DlDynlib {
310315 return DlDynlib{
311 .handle = system.dlopen(path.ptr, system.RTLD_LAZY) orelse {
316 .handle = system.dlopen(path_c, system.RTLD_LAZY) orelse {
312317 return error.FileNotFound;
313318 },
314319 };
......@@ -319,20 +324,15 @@ pub const DlDynlib = struct {
319324 self.* = undefined;
320325 }
321326
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| {
324331 return @ptrCast(T, symbol);
325332 } else {
326333 return null;
327334 }
328335 }
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 }
336336};
337337
338338test "dynamic_library" {
......@@ -340,7 +340,7 @@ test "dynamic_library" {
340340 .linux => "invalid_so.so",
341341 .windows => "invalid_dll.dll",
342342 .macosx, .tvos, .watchos, .ios => "invalid_dylib.dylib",
343 else => return,
343 else => return error.SkipZigTest,
344344 };
345345
346346 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
65616561}
65626562
65636563static IrInstruction *ir_expr_wrap(IrBuilder *irb, Scope *scope, IrInstruction *inst, ResultLoc *result_loc) {
6564 if (inst == irb->codegen->invalid_instruction) return inst;
65646565 ir_build_end_expr(irb, scope, inst->source_node, inst, result_loc);
65656566 return inst;
65666567}
test/standalone.zig+4-9
......@@ -1,6 +1,5 @@
1const std = @import("std");
12const tests = @import("tests.zig");
2const builtin = @import("builtin");
3const is_windows = builtin.os == builtin.Os.windows;
43
54pub fn addCases(cases: *tests.StandaloneContext) void {
65 cases.add("test/standalone/hello_world/hello.zig");
......@@ -19,14 +18,10 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
1918 cases.addBuildFile("test/standalone/use_alias/build.zig");
2019 cases.addBuildFile("test/standalone/brace_expansion/build.zig");
2120 cases.addBuildFile("test/standalone/empty_env/build.zig");
22 switch (builtin.os) {
23 .linux, .windows, .macosx, .tvos, .watchos, .ios => {
24 cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");
25 },
26 else => {},
21 if (std.Target.current.getOs() != .wasi) {
22 cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");
2723 }
28
29 if (builtin.arch == builtin.Arch.x86_64) { // TODO add C ABI support for other architectures
24 if (std.Target.current.getArch() == .x86_64) { // TODO add C ABI support for other architectures
3025 cases.addBuildFile("test/stage1/c_abi/build.zig");
3126 }
3227}