-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Added DLL loading capability in windows to the std lib. Ensure that t… #616
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,11 @@ | |
#include "codegen.hpp" | ||
#include "analyze.hpp" | ||
|
||
#ifdef ZIG_OS_WINDOWS | ||
#define WIN32_LEAN_AND_MEAN | ||
#include <Windows.h> | ||
#endif | ||
|
||
struct LinkJob { | ||
CodeGen *codegen; | ||
Buf out_file; | ||
|
@@ -488,18 +493,28 @@ static void construct_linker_job_coff(LinkJob *lj) { | |
if (lj->codegen->zig_target.env_type == ZigLLVM_GNU) { | ||
Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name)); | ||
lj->args.append(buf_ptr(arg)); | ||
} | ||
else { | ||
} else { | ||
lj->args.append(buf_ptr(link_lib->name)); | ||
} | ||
} else { | ||
buf_resize(def_contents, 0); | ||
buf_appendf(def_contents, "LIBRARY %s\nEXPORTS\n", buf_ptr(link_lib->name)); | ||
#ifdef ZIG_OS_WINDOWS | ||
Buf* dll_name = buf_create_from_buf(link_lib->name); | ||
buf_append_str(dll_name, ".dll"); | ||
HMODULE hmod = GetModuleHandle(buf_ptr(dll_name)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From MSDN GetModuleHandle:
Based on this, I think we have to use LoadLibrary before GetModuleHandle. And LoadLibrary runs the code in the DLL, which can crash the compiler. So we should do it in a child process, and communicate back to zig compiler the results. If we're going to spawn a child process, we might as well write that child process in zig and build it lazily just like compiler_rt.o and builtin.o. |
||
assert(hmod); | ||
for (size_t exp_i = 0; exp_i < link_lib->symbols.length; exp_i += 1) { | ||
Buf *symbol_name = link_lib->symbols.at(exp_i); | ||
FARPROC symbol_addr = GetProcAddress(hmod, buf_ptr(symbol_name)); | ||
if (symbol_addr == NULL) { | ||
fprintf(stderr, "error: extern symbol: %s does not exist in: %s.\n", buf_ptr(symbol_name), buf_ptr(dll_name)); | ||
exit(1); | ||
} | ||
buf_appendf(def_contents, "%s\n", buf_ptr(symbol_name)); | ||
} | ||
buf_appendf(def_contents, "\n"); | ||
#endif | ||
|
||
Buf *def_path = buf_alloc(); | ||
os_path_join(g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,6 +84,11 @@ pub extern "kernel32" stdcallcc fn WriteFile(in_hFile: HANDLE, in_lpBuffer: &con | |
in_nNumberOfBytesToWrite: DWORD, out_lpNumberOfBytesWritten: ?&DWORD, | ||
in_out_lpOverlapped: ?&OVERLAPPED) -> BOOL; | ||
|
||
//TODO: call unicode versions instead of relying on ANSI code page | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. link to #534 |
||
pub extern "kernel32" stdcallcc fn LoadLibraryA(lpLibFileName: LPCSTR) -> ?HMODULE; | ||
|
||
pub extern "kernel32" stdcallcc fn FreeLibrary(hModule: HMODULE) -> BOOL; | ||
|
||
pub extern "user32" stdcallcc fn MessageBoxA(hWnd: ?HANDLE, lpText: ?LPCTSTR, lpCaption: ?LPCTSTR, uType: UINT) -> c_int; | ||
|
||
pub const PROV_RSA_FULL = 1; | ||
|
@@ -97,6 +102,7 @@ pub const FLOAT = f32; | |
pub const HANDLE = &c_void; | ||
pub const HCRYPTPROV = ULONG_PTR; | ||
pub const HINSTANCE = &@OpaqueType(); | ||
pub const HMODULE = &@OpaqueType(); | ||
pub const INT = c_int; | ||
pub const LPBYTE = &BYTE; | ||
pub const LPCH = &CHAR; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ const windows = std.os.windows; | |
const assert = std.debug.assert; | ||
const mem = std.mem; | ||
const BufMap = std.BufMap; | ||
const cstr = std.cstr; | ||
|
||
error WaitAbandoned; | ||
error WaitTimeOut; | ||
|
@@ -149,3 +150,19 @@ pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) | |
result[i] = 0; | ||
return result; | ||
} | ||
|
||
error DllNotFound; | ||
pub fn windowsLoadDll(allocator: &mem.Allocator, dll_path: []const u8) -> %windows.HMODULE { | ||
const padded_buff = %return cstr.addNullByte(allocator, dll_path); | ||
defer allocator.free(padded_buff); | ||
const rc = windows.LoadLibraryA(padded_buff.ptr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if(rc == null) { | ||
return error.DllNotFound; | ||
} else { | ||
return @ptrCast(windows.HMODULE, rc); | ||
} | ||
} | ||
|
||
pub fn windowsUnloadDll(hModule: windows.HMODULE) { | ||
assert(windows.FreeLibrary(hModule)!= 0); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pattern we have so far is to isolate windows API calls to os.cpp. That should be the only file that includes windows.h.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that makes sense, I'll move the verification code to there.