2

Is it possible, to in Windows, create a GUI program, which has it's entry point in 'main()'? How do I do this?

My use for this is that I want a cross-platform application, with one uniform entry point.

Jeroen
  • 15,257
  • 12
  • 59
  • 102
  • In C++ at least, you can use `main()` and still create UI. The only thing the name `main` does is trigger the toolchain to use the `CONSOLE` subsystem, but you can override that. I would not expect D to be any different. – Ben Voigt Dec 13 '13 at 19:00
  • Also, an uniform entry point isn't as valuable as it sounds. You don't have to do anything in the entrypoint itself, all entrypoints can be single-line functions that call your common startup code. – Ben Voigt Dec 13 '13 at 19:01
  • @BenVoigt If it's the linger which overrides it, it probably works the same way in D. How would you do it in D? - Also I do realize the main thing but I'd like my application to be modular; and simply load modules based on platform. – Jeroen Dec 13 '13 at 19:01
  • In C++, after compiling `main()` and linking, I would run `editbin /SUBSYSTEM:WINDOWS whatever.exe` – Ben Voigt Dec 13 '13 at 19:03
  • @BenVoigt Thanks, you can put that as an answer. ;) – Jeroen Dec 13 '13 at 19:05
  • @BenVoigt Surely that's too late. Where will WinMain appear from? The entry point will have the wrong signature surely. – David Heffernan Dec 13 '13 at 19:07
  • @DavidHeffernan: The real entrypoint is provided by the CRT. And its signature (naked calling convention, no arguments, never returns) doesn't depend on the subsystem. Arguments to both `main` and `WinMain` don't come as arguments for the real entrypoint, but from Win32 API calls such as `GetModuleHandle` and `GetCommandLine(A|W)` – Ben Voigt Dec 13 '13 at 19:10
  • @DavidHeffernan: Have you ever used `setargv.obj` to enable globbing? It works because on Windows `argc` and `argv` are constructed by the runtime library, not the OS. [More here](http://msdn.microsoft.com/en-us/library/ah6y4f3z.aspx) – Ben Voigt Dec 13 '13 at 19:15
  • @BenVoigt I have not. As I think you know, VS and C++ is not my home environment. I like how that MSDN document mentions setargv as a way to suppress arg processing, but you use it to enable blobbing!! Nice. – David Heffernan Dec 13 '13 at 19:22
  • @DavidHeffernan: They mention that too. http://msdn.microsoft.com/en-us/library/8bch7bkk.aspx – Ben Voigt Dec 13 '13 at 19:24
  • @David The commercial editions of Visual Studio come with (almost complete) source code for the CRT. If you're interested to see the application startup code, have a look at crt0.c (vc/crt/src directory). – IInspectable Dec 14 '13 at 00:12

1 Answers1

6
  1. Write your application using main() and all the GUI calls in there that you would have used in WinMain. This will create an application with both a GUI and a console window.
  2. Use the Windows SDK tool editbin /SUBSYSTEM:WINDOWS appname.exe to change the subsystem flag in the PE header, so Windows won't create a console window automatically.
  3. If you want to have a working stdout for debug message or the like, you can either use freopen to direct stdout to a file, or AllocConsole when you decide a console window is needed (for example, after an error occurs).

BTW: This thread indicates that the DMD compiler will prefer main() over WinMain() anyway if it finds both.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • With dmd on Win32, you can also pass `-L/SUBSYSTEM:WINDOWS` to dmd and skip the editbin step - `-L` will pass the argument to the linker, and optlink understands the subsystem command. – Adam D. Ruppe Dec 13 '13 at 22:04
  • @Adam: And that won't cause it to look for `WinMain`? The reason for this sequence is to deceive the linker with `/SUBSYSTEM:CONSOLE` so that the startup code which gets parameters to `main()` and not `WinMain()` will be used. None of that startup code actually has anything to do with which subsystem is used, it's just a convention, enforced by the Microsoft linker. – Ben Voigt Dec 13 '13 at 22:10
  • Not sure about 64 bit which uses the Microsoft linker, but on 32 bit, dmd uses the Optlink linker and I've done it with main() with the windows subsystem before and everything worked. – Adam D. Ruppe Dec 13 '13 at 22:34
  • @Adam: I was thinking that Optlink would probably strive for compatibility. On the other hand, this only affects the default C and C++ runtime libraries, and the D toolchain probably invokes the linker with `/NODEFAULTLIB` and explicitly provides its own runtime and startup code. – Ben Voigt Dec 14 '13 at 00:43