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 @@...@@ -1,10 +1,23 @@
1const builtin = @import("builtin");
2const Os = builtin.Os;
3
1const std = @import("index.zig");4const std = @import("index.zig");
2const mem = std.mem;5const mem = std.mem;
3const elf = std.elf;
4const cstr = std.cstr;6const 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 {
8 allocator: *mem.Allocator,21 allocator: *mem.Allocator,
9 elf_lib: ElfLib,22 elf_lib: ElfLib,
10 fd: i32,23 fd: i32,
...@@ -107,7 +120,7 @@ pub const ElfLib = struct {...@@ -107,7 +120,7 @@ pub const ElfLib = struct {
107 }120 }
108 }121 }
109122
110 return ElfLib{123 return ElfLib {
111 .base = base,124 .base = base,
112 .strings = maybe_strings orelse return error.ElfStringSectionNotFound,125 .strings = maybe_strings orelse return error.ElfStringSectionNotFound,
113 .syms = maybe_syms orelse return error.ElfSymSectionNotFound,126 .syms = maybe_syms orelse return error.ElfSymSectionNotFound,
...@@ -154,3 +167,48 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [...@@ -154,3 +167,48 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [
154 const aux = @intToPtr(*elf.Verdaux, @ptrToInt(def) + def.vd_aux);167 const aux = @intToPtr(*elf.Verdaux, @ptrToInt(def) + def.vd_aux);
155 return mem.eql(u8, vername, cstr.toSliceConst(strings + aux.vda_name));168 return mem.eql(u8, vername, cstr.toSliceConst(strings + aux.vda_name));
156}169}
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;...@@ -58,8 +58,6 @@ pub const windowsWrite = windows_util.windowsWrite;
58pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty;58pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty;
59pub const windowsOpen = windows_util.windowsOpen;59pub const windowsOpen = windows_util.windowsOpen;
60pub const windowsOpenW = windows_util.windowsOpenW;60pub const windowsOpenW = windows_util.windowsOpenW;
61pub const windowsLoadDll = windows_util.windowsLoadDll;
62pub const windowsUnloadDll = windows_util.windowsUnloadDll;
63pub const createWindowsEnvBlock = windows_util.createWindowsEnvBlock;61pub const createWindowsEnvBlock = windows_util.createWindowsEnvBlock;
6462
65pub const WindowsCreateIoCompletionPortError = windows_util.WindowsCreateIoCompletionPortError;63pub const WindowsCreateIoCompletionPortError = windows_util.WindowsCreateIoCompletionPortError;
std/os/windows/index.zig+1
...@@ -24,6 +24,7 @@ pub const HANDLE = *c_void;...@@ -24,6 +24,7 @@ pub const HANDLE = *c_void;
24pub const HCRYPTPROV = ULONG_PTR;24pub const HCRYPTPROV = ULONG_PTR;
25pub const HINSTANCE = *@OpaqueType();25pub const HINSTANCE = *@OpaqueType();
26pub const HMODULE = *@OpaqueType();26pub const HMODULE = *@OpaqueType();
27pub const FARPROC = *@OpaqueType();
27pub const INT = c_int;28pub const INT = c_int;
28pub const LPBYTE = *BYTE;29pub const LPBYTE = *BYTE;
29pub const LPCH = *CHAR;30pub const LPCH = *CHAR;
std/os/windows/kernel32.zig+2
...@@ -178,6 +178,8 @@ pub extern "kernel32" stdcallcc fn WriteFileEx(hFile: HANDLE, lpBuffer: [*]const...@@ -178,6 +178,8 @@ pub extern "kernel32" stdcallcc fn WriteFileEx(hFile: HANDLE, lpBuffer: [*]const
178178
179pub extern "kernel32" stdcallcc fn LoadLibraryW(lpLibFileName: [*]const u16) ?HMODULE;179pub extern "kernel32" stdcallcc fn LoadLibraryW(lpLibFileName: [*]const u16) ?HMODULE;
180180
181pub extern "kernel32" stdcallcc fn GetProcAddress(hModule: HMODULE, lpProcName: [*]const u8) ?FARPROC;
182
181pub extern "kernel32" stdcallcc fn FreeLibrary(hModule: HMODULE) BOOL;183pub extern "kernel32" stdcallcc fn FreeLibrary(hModule: HMODULE) BOOL;
182184
183pub const FILE_NOTIFY_INFORMATION = extern struct {185pub 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)...@@ -188,37 +188,6 @@ pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap)
188 return allocator.shrink(u16, result, i);188 return allocator.shrink(u16, result, i);
189}189}
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
222pub fn windowsFindFirstFile(191pub fn windowsFindFirstFile(
223 dir_path: []const u8,192 dir_path: []const u8,
224 find_file_data: *windows.WIN32_FIND_DATAW,193 find_file_data: *windows.WIN32_FIND_DATAW,