| author | |
| committer | |
| log | 04481c76cb5f2ec78bf4b10c0cdb090e8a64240e |
| tree | aed39038b525abe6d42341769a69e1b1826b4bb8 |
| parent | 1f22b2cbb2d9cdc4b7e436328e7018f473a57388 |
| parent | a450016eb1816a8f0989626dde4b0c1865cba33d |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/32179
Reviewed-by: Andrew Kelley <andrew@ziglang.org>5 files changed, 124 insertions(+), 1 deletions(-)
lib/std/start.zig+13-1| ... | @@ -23,6 +23,10 @@ comptime { | ... | @@ -23,6 +23,10 @@ comptime { |
| 23 | const dll_main_crt_startup = if (builtin.abi.isGnu()) "DllMainCRTStartup" else "_DllMainCRTStartup"; | 23 | const dll_main_crt_startup = if (builtin.abi.isGnu()) "DllMainCRTStartup" else "_DllMainCRTStartup"; |
| 24 | if (native_os == .windows and !builtin.link_libc and !@hasDecl(root, dll_main_crt_startup)) { | 24 | if (native_os == .windows and !builtin.link_libc and !@hasDecl(root, dll_main_crt_startup)) { |
| 25 | @export(&DllMainCRTStartup, .{ .name = dll_main_crt_startup }); | 25 | @export(&DllMainCRTStartup, .{ .name = dll_main_crt_startup }); |
| 26 | } else if (native_os == .windows and builtin.link_libc and @hasDecl(root, "DllMain")) { | ||
| 27 | if (!@typeInfo(@TypeOf(root.DllMain)).@"fn".calling_convention.eql(.winapi)) { | ||
| 28 | @export(&DllMain, .{ .name = "DllMain" }); | ||
| 29 | } | ||
| 26 | } | 30 | } |
| 27 | } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { | 31 | } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { |
| 28 | if (builtin.link_libc and @hasDecl(root, "main")) { | 32 | if (builtin.link_libc and @hasDecl(root, "main")) { |
| ... | @@ -82,12 +86,20 @@ fn DllMainCRTStartup( | ... | @@ -82,12 +86,20 @@ fn DllMainCRTStartup( |
| 82 | } | 86 | } |
| 83 | 87 | ||
| 84 | if (@hasDecl(root, "DllMain")) { | 88 | if (@hasDecl(root, "DllMain")) { |
| 85 | return root.DllMain(hinstDLL, fdwReason, lpReserved); | 89 | return root.DllMain(@ptrCast(hinstDLL), fdwReason, lpReserved); |
| 86 | } | 90 | } |
| 87 | 91 | ||
| 88 | return .TRUE; | 92 | return .TRUE; |
| 89 | } | 93 | } |
| 90 | 94 | ||
| 95 | fn DllMain( | ||
| 96 | hinstDLL: std.os.windows.HINSTANCE, | ||
| 97 | fdwReason: std.os.windows.DWORD, | ||
| 98 | lpReserved: std.os.windows.LPVOID, | ||
| 99 | ) callconv(.winapi) std.os.windows.BOOL { | ||
| 100 | return root.DllMain(@ptrCast(hinstDLL), fdwReason, lpReserved); | ||
| 101 | } | ||
| 102 | |||
| 91 | fn wasm_freestanding_start() callconv(.c) void { | 103 | fn wasm_freestanding_start() callconv(.c) void { |
| 92 | // This is marked inline because for some reason LLVM in | 104 | // This is marked inline because for some reason LLVM in |
| 93 | // release mode fails to inline it, and we want fewer call frames in stack traces. | 105 | // release mode fails to inline it, and we want fewer call frames in stack traces. |
test/standalone/windows_entry_points/build.zig+71| ... | @@ -139,4 +139,75 @@ pub fn build(b: *std.Build) void { | ... | @@ -139,4 +139,75 @@ pub fn build(b: *std.Build) void { |
| 139 | _ = exe.getEmittedBin(); | 139 | _ = exe.getEmittedBin(); |
| 140 | test_step.dependOn(&exe.step); | 140 | test_step.dependOn(&exe.step); |
| 141 | } | 141 | } |
| 142 | |||
| 143 | const load_dll_exe = b.addExecutable(.{ .name = "load_dll", .root_module = b.createModule(.{ | ||
| 144 | .root_source_file = b.path("loaddll.zig"), | ||
| 145 | .target = target, | ||
| 146 | .optimize = .Debug, | ||
| 147 | }) }); | ||
| 148 | |||
| 149 | { | ||
| 150 | const dll = b.addLibrary(.{ | ||
| 151 | .name = "zig_dllmain", | ||
| 152 | .linkage = .dynamic, | ||
| 153 | .root_module = b.createModule(.{ | ||
| 154 | .root_source_file = b.path("dllmain.zig"), | ||
| 155 | .target = target, | ||
| 156 | .optimize = .Debug, | ||
| 157 | }), | ||
| 158 | }); | ||
| 159 | |||
| 160 | const run = b.addRunArtifact(load_dll_exe); | ||
| 161 | run.addArtifactArg(dll); | ||
| 162 | run.expectStdErrEqual("hello from DllMain"); | ||
| 163 | run.expectStdOutEqual(""); | ||
| 164 | run.expectExitCode(0); | ||
| 165 | run.skip_foreign_checks = true; | ||
| 166 | |||
| 167 | test_step.dependOn(&run.step); | ||
| 168 | } | ||
| 169 | |||
| 170 | { | ||
| 171 | const dll = b.addLibrary(.{ | ||
| 172 | .name = "zig_dllmain_link_libc", | ||
| 173 | .linkage = .dynamic, | ||
| 174 | .root_module = b.createModule(.{ | ||
| 175 | .root_source_file = b.path("dllmain.zig"), | ||
| 176 | .target = target, | ||
| 177 | .optimize = .Debug, | ||
| 178 | .link_libc = true, | ||
| 179 | }), | ||
| 180 | }); | ||
| 181 | |||
| 182 | const run = b.addRunArtifact(load_dll_exe); | ||
| 183 | run.addArtifactArg(dll); | ||
| 184 | run.expectStdErrEqual("hello from DllMain"); | ||
| 185 | run.expectStdOutEqual(""); | ||
| 186 | run.expectExitCode(0); | ||
| 187 | run.skip_foreign_checks = true; | ||
| 188 | |||
| 189 | test_step.dependOn(&run.step); | ||
| 190 | } | ||
| 191 | |||
| 192 | { | ||
| 193 | const dll = b.addLibrary(.{ | ||
| 194 | .name = "c_dllmain", | ||
| 195 | .linkage = .dynamic, | ||
| 196 | .root_module = b.createModule(.{ | ||
| 197 | .target = target, | ||
| 198 | .optimize = .Debug, | ||
| 199 | .link_libc = true, | ||
| 200 | }), | ||
| 201 | }); | ||
| 202 | dll.root_module.addCSourceFile(.{ .file = b.path("dllmain.c") }); | ||
| 203 | |||
| 204 | const run = b.addRunArtifact(load_dll_exe); | ||
| 205 | run.addArtifactArg(dll); | ||
| 206 | run.expectStdErrEqual("hello from DllMain"); | ||
| 207 | run.expectStdOutEqual(""); | ||
| 208 | run.expectExitCode(0); | ||
| 209 | run.skip_foreign_checks = true; | ||
| 210 | |||
| 211 | test_step.dependOn(&run.step); | ||
| 212 | } | ||
| 142 | } | 213 | } |
test/standalone/windows_entry_points/dllmain.c created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | #include <windows.h> | ||
| 2 | #include <stdio.h> | ||
| 3 | |||
| 4 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { | ||
| 5 | if (fdwReason == DLL_PROCESS_ATTACH) { | ||
| 6 | fprintf(stderr, "hello from DllMain"); | ||
| 7 | } | ||
| 8 | return TRUE; | ||
| 9 | } | ||
test/standalone/windows_entry_points/dllmain.zig created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const windows = std.os.windows; | ||
| 3 | |||
| 4 | const DLL_PROCESS_ATTACH = 1; | ||
| 5 | |||
| 6 | pub fn DllMain( | ||
| 7 | hinstDLL: windows.HINSTANCE, | ||
| 8 | fdwReason: windows.DWORD, | ||
| 9 | lpReserved: windows.LPVOID, | ||
| 10 | ) windows.BOOL { | ||
| 11 | _ = hinstDLL; | ||
| 12 | _ = lpReserved; | ||
| 13 | switch (fdwReason) { | ||
| 14 | DLL_PROCESS_ATTACH => std.debug.print("hello from DllMain", .{}), | ||
| 15 | else => {}, | ||
| 16 | } | ||
| 17 | return .TRUE; | ||
| 18 | } | ||
test/standalone/windows_entry_points/loaddll.zig created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const windows = std.os.windows; | ||
| 3 | |||
| 4 | extern "kernel32" fn LoadLibraryW(windows.LPCWSTR) callconv(.winapi) ?windows.HMODULE; | ||
| 5 | |||
| 6 | pub fn main(init: std.process.Init) !void { | ||
| 7 | const arena = init.arena.allocator(); | ||
| 8 | const args = try init.minimal.args.toSlice(arena); | ||
| 9 | if (args.len < 2) return error.NoDllPathSpecified; | ||
| 10 | const dll_path = args[1]; | ||
| 11 | const dll_path_w = try std.unicode.wtf8ToWtf16LeAllocZ(arena, dll_path); | ||
| 12 | _ = LoadLibraryW(dll_path_w) orelse return error.FailedToLoadDll; | ||
| 13 | } | ||