authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-30 09:31:24-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-09-30 09:31:24-04:00
loga42a213e35842e18750dd8cfdfc0d024e23da50b
treee766cb115890713ec2d5522e3f5ba59032dd881a
parente6446dfc86e42ccea93760d99cf4b421265cfb0e
parent623f5085f152b3a2fedf3b4e4451910f1edb6739
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #1594 from emekoi/master

added dynamic library loading for windows

5 files changed, 65 insertions(+), 37 deletions(-)

std/dynamic_library.zig+62-4
......@@ -1,10 +1,23 @@
1const builtin = @import("builtin");
2const Os = builtin.Os;
3
14const std = @import("index.zig");
25const mem = std.mem;
3const elf = std.elf;
46const cstr = std.cstr;
5const linux = std.os.linux;
7const os = std.os;
8const assert = std.debug.assert;
9const elf = std.elf;
10const linux = os.linux;
11const windows = os.windows;
12const win_util = @import("os/windows/util.zig");
13
14pub const DynLib = switch (builtin.os) {
15 Os.linux => LinuxDynLib,
16 Os.windows => WindowsDynLib,
17 else => void,
18};
619
7pub const DynLib = struct {
20pub const LinuxDynLib = struct {
821 allocator: *mem.Allocator,
922 elf_lib: ElfLib,
1023 fd: i32,
......@@ -107,7 +120,7 @@ pub const ElfLib = struct {
107120 }
108121 }
109122
110 return ElfLib{
123 return ElfLib {
111124 .base = base,
112125 .strings = maybe_strings orelse return error.ElfStringSectionNotFound,
113126 .syms = maybe_syms orelse return error.ElfSymSectionNotFound,
......@@ -154,3 +167,48 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [
154167 const aux = @intToPtr(*elf.Verdaux, @ptrToInt(def) + def.vd_aux);
155168 return mem.eql(u8, vername, cstr.toSliceConst(strings + aux.vda_name));
156169}
170
171pub const WindowsDynLib = struct {
172 allocator: *mem.Allocator,
173 dll: windows.HMODULE,
174
175 pub fn open(allocator: *mem.Allocator, path: []const u8) !WindowsDynLib {
176 const wpath = try win_util.sliceToPrefixedFileW(path);
177
178 return WindowsDynLib {
179 .allocator = allocator,
180 .dll = windows.LoadLibraryW(&wpath) orelse {
181 const err = windows.GetLastError();
182 switch (err) {
183 windows.ERROR.FILE_NOT_FOUND => return error.FileNotFound,
184 windows.ERROR.PATH_NOT_FOUND => return error.FileNotFound,
185 windows.ERROR.MOD_NOT_FOUND => return error.FileNotFound,
186 else => return os.unexpectedErrorWindows(err),
187 }
188 },
189 };
190 }
191
192 pub fn close(self: *WindowsDynLib) void {
193 assert(windows.FreeLibrary(self.dll) != 0);
194 self.* = undefined;
195 }
196
197 pub fn lookup(self: *WindowsDynLib, name: []const u8) ?usize {
198 return @ptrToInt(windows.GetProcAddress(self.dll, name.ptr));
199 }
200};
201
202test "dynamic_library" {
203 const libname = switch (builtin.os) {
204 Os.linux => "invalid_so.so",
205 Os.windows => "invalid_dll.dll",
206 else => return;,
207 };
208
209 const dynlib = DynLib.open(std.debug.global_allocator, libname) catch |err| {
210 assert(err == error.FileNotFound);
211 return;
212 };
213 @panic("Expected error from function");
214}
std/os/index.zig-2
......@@ -58,8 +58,6 @@ pub const windowsWrite = windows_util.windowsWrite;
5858pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty;
5959pub const windowsOpen = windows_util.windowsOpen;
6060pub const windowsOpenW = windows_util.windowsOpenW;
61pub const windowsLoadDll = windows_util.windowsLoadDll;
62pub const windowsUnloadDll = windows_util.windowsUnloadDll;
6361pub const createWindowsEnvBlock = windows_util.createWindowsEnvBlock;
6462
6563pub const WindowsCreateIoCompletionPortError = windows_util.WindowsCreateIoCompletionPortError;
std/os/windows/index.zig+1
......@@ -24,6 +24,7 @@ pub const HANDLE = *c_void;
2424pub const HCRYPTPROV = ULONG_PTR;
2525pub const HINSTANCE = *@OpaqueType();
2626pub const HMODULE = *@OpaqueType();
27pub const FARPROC = *@OpaqueType();
2728pub const INT = c_int;
2829pub const LPBYTE = *BYTE;
2930pub const LPCH = *CHAR;
std/os/windows/kernel32.zig+2
......@@ -178,6 +178,8 @@ pub extern "kernel32" stdcallcc fn WriteFileEx(hFile: HANDLE, lpBuffer: [*]const
178178
179179pub extern "kernel32" stdcallcc fn LoadLibraryW(lpLibFileName: [*]const u16) ?HMODULE;
180180
181pub extern "kernel32" stdcallcc fn GetProcAddress(hModule: HMODULE, lpProcName: [*]const u8) ?FARPROC;
182
181183pub extern "kernel32" stdcallcc fn FreeLibrary(hModule: HMODULE) BOOL;
182184
183185pub const FILE_NOTIFY_INFORMATION = extern struct {
std/os/windows/util.zig-31
......@@ -188,37 +188,6 @@ pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap)
188188 return allocator.shrink(u16, result, i);
189189}
190190
191pub fn windowsLoadDllW(dll_path_w: [*]const u16) !windows.HMODULE {
192 return windows.LoadLibraryW(dll_path_w) orelse {
193 const err = windows.GetLastError();
194 switch (err) {
195 windows.ERROR.FILE_NOT_FOUND => return error.FileNotFound,
196 windows.ERROR.PATH_NOT_FOUND => return error.FileNotFound,
197 windows.ERROR.MOD_NOT_FOUND => return error.FileNotFound,
198 else => return os.unexpectedErrorWindows(err),
199 }
200 };
201}
202
203pub fn windowsLoadDll(dll_path: []const u8) !windows.HMODULE {
204 const dll_path_w = try sliceToPrefixedFileW(dll_path);
205 return windowsLoadDllW(&dll_path_w);
206}
207
208pub fn windowsUnloadDll(hModule: windows.HMODULE) void {
209 assert(windows.FreeLibrary(hModule) != 0);
210}
211
212test "InvalidDll" {
213 if (builtin.os != builtin.Os.windows) return error.SkipZigTest;
214
215 const handle = os.windowsLoadDll("asdf.dll") catch |err| {
216 assert(err == error.FileNotFound);
217 return;
218 };
219 @panic("Expected error from function");
220}
221
222191pub fn windowsFindFirstFile(
223192 dir_path: []const u8,
224193 find_file_data: *windows.WIN32_FIND_DATAW,