digitalmars.D.learn - Abstractioning away main/winMain
- Prudence (38/38) Sep 04 2015 Standard and Win32 apps are so old school!
- Adam D. Ruppe (13/18) Sep 04 2015 If you use WinMain in D, you'll also have to initialize the D
- Prudence (13/31) Sep 04 2015 Maybe, but the error relates to be being called statically.
- Prudence (11/11) Sep 04 2015 If I use functions instead of delegates it works.
- Alex Parrill (7/18) Sep 04 2015 How would the X instance get passed in?
- anonymous (62/116) Sep 04 2015 Please provide self-contained code. Without key details it's hard to
- anonymous (2/14) Sep 04 2015
- Kagamin (2/3) Sep 07 2015 See how vibe does it.
Standard and Win32 apps are so old school! I'd like to hide WinMain by wrapping it in an application class(more or less). Essentially I have an Application class class Application { public static Application New(void delegate() entry) { } } .... Another module extern (Windows) int WinMain(...) { } .... User Module: const MyApp = Application.New({ std.stdio.writeln("MY APP IS COOL"); }); But the lamba runs into a problem because of the static nature of the program... much less figuring out how to hook WinMain up into it. Essentially I don't want the user ever to have to know how there entry point came into being but there is this funkyness about it because Application never gets any control to call the user's Entry function. Whats worse is that D tries to evaluate the lambda at compile time. It's as if D only allows non-static data inside functions. The idea is to have WinMain actually call the Entry lamba function once it gets ran(transfer control)... but this seems to be difficult or impossible with D and I'm not sure why or, if not, how to get it to work without having to make the user jump through hoops. I suppose I could create the Application(Using New instead of new) inside of WinMain, but the issue still remains on how to get the user entry point(I suppose some compile time reflection could be used?). Any ideas? (The main reason for doing this is to make it easier for writing portable apps)
Sep 04 2015
On Saturday, 5 September 2015 at 01:43:43 UTC, Prudence wrote:extern (Windows) int WinMain(...)If you use WinMain in D, you'll also have to initialize the D runtime yourself, which will call static constructors and such. You'd be better off just using a regular main() function, then passing the `-L/SUBSYSTEM:WINDOWS:5.0` option to dmd when building (at least on 32 bit, not sure if it is the same on 64 bit or not) so the linker makes a gui app - same as it does when it detects a WinMain in the program.const MyApp = Application.New({ std.stdio.writeln("MY APP IS COOL"); });Remember, gui apps don't necessarily have a console, so writeln may fail!(The main reason for doing this is to make it easier for writing portable apps)Just using a regular main function is the most portable solution. Then just offer helper functions or something to help with the boilerplate.
Sep 04 2015
On Saturday, 5 September 2015 at 01:49:22 UTC, Adam D. Ruppe wrote:On Saturday, 5 September 2015 at 01:43:43 UTC, Prudence wrote:Maybe, but the error relates to be being called statically.extern (Windows) int WinMain(...)If you use WinMain in D, you'll also have to initialize the D runtime yourself, which will call static constructors and such. You'd be better off just using a regular main() function, then passing the `-L/SUBSYSTEM:WINDOWS:5.0` option to dmd when building (at least on 32 bit, not sure if it is the same on 64 bit or not) so the linker makes a gui app - same as it does when it detects a WinMain in the program.const MyApp = Application.New({ std.stdio.writeln("MY APP IS COOL"); });Remember, gui apps don't necessarily have a console, so writeln may fail!Essentially that is what I'm doing. I have divided the app into different types using versioning. The application class is a generic wrapper for the main possibilities(win32, Win64, mac, linux, etc). Basically WinMain is used when version is Win32 or Win64 so it is not a problem with the stuff you have mentioned. At some point I will make it all work but I need to get off the ground first. I can always force the user to jump through some hoops but I'd like to avoid that as much as possible since I'm the user and I don't like hoops.(The main reason for doing this is to make it easier for writing portable apps)Just using a regular main function is the most portable solution. Then just offer helper functions or something to help with the boilerplate.
Sep 04 2015
If I use functions instead of delegates it works. I suppose the problem then is that the delegate can't create a fat pointer when used in a static context. (i.e., why the functions work) The question is, then, Can I construct a delegate manually and supply my own context pointer? e.g., class X { } void foo() { } constructDelegate(&foo, new X()) // Creates a void delegate() with context X
Sep 04 2015
On Saturday, 5 September 2015 at 02:29:05 UTC, Prudence wrote:If I use functions instead of delegates it works. I suppose the problem then is that the delegate can't create a fat pointer when used in a static context. (i.e., why the functions work) The question is, then, Can I construct a delegate manually and supply my own context pointer? e.g., class X { } void foo() { } constructDelegate(&foo, new X()) // Creates a void delegate() with context XHow would the X instance get passed in? You could try this: class X {} void foo(X x) {} auto x = new X(); auto dg = () => foo(x);
Sep 04 2015
On Saturday 05 September 2015 03:43, Prudence wrote:Standard and Win32 apps are so old school! I'd like to hide WinMain by wrapping it in an application class(more or less). Essentially I have an Application class class Application { public static Application New(void delegate() entry) { } } .... Another module extern (Windows) int WinMain(...) { } .... User Module: const MyApp = Application.New({ std.stdio.writeln("MY APP IS COOL"); }); But the lamba runs into a problem because of the static nature of the program... much less figuring out how to hook WinMain up into it.Please provide self-contained code. Without key details it's hard to understand where things are going wrong. I'm guessing your actual code essentially tries to do this: ---- class Application { void delegate() entry; public static Application New(void delegate() entry) { auto a = new Application; a.entry = entry; return a; } } const MyApp = Application.New({import std.stdio; std.stdio.writeln("MY APP IS COOL"); }); /* Error: non-constant nested delegate literal expression __lambda6 */ void main() /* or WinMain */ { MyApp.entry(); } ---- This doesn't work because delegates and static initialization don't go together. You can use a static constructor: ---- const Application MyApp; static this() { Application.New({import std.stdio; std.stdio.writeln("MY APP IS COOL"); }); } ---- Or you can make `entry` a function instead of a delegate: ---- class Application { void function() entry; public static Application New(void function() entry) { ... } } ----Essentially I don't want the user ever to have to know how there entry point came into being but there is this funkyness about it because Application never gets any control to call the user's Entry function. Whats worse is that D tries to evaluate the lambda at compile time. It's as if D only allows non-static data inside functions. The idea is to have WinMain actually call the Entry lamba function once it gets ran(transfer control)... but this seems to be difficult or impossible with D and I'm not sure why or, if not, how to get it to work without having to make the user jump through hoops. I suppose I could create the Application(Using New instead of new) inside of WinMain, but the issue still remains on how to get the user entry point(I suppose some compile time reflection could be used?). Any ideas?I'm probably being naive and the following falls short somehow, but how about this: ---- /* your module */ void function() userMain; void main() /* or WinMain */ { /* ... stuff ... */ userMain(); /* ... stuff ... */ } /* user module: */ /* import your module; */ static this() { userMain = {import std.stdio; std.stdio.writeln("MY APP IS COOL"); }; } ----
Sep 04 2015
On Saturday 05 September 2015 07:52, anonymous wrote:This doesn't work because delegates and static initialization don't go together. You can use a static constructor: ---- const Application MyApp; static this() { Application.New({import std.stdio; std.stdio.writeln("MY APP IS COOL");Should be: MyApp = Application.New({...});}); } ----
Sep 04 2015
On Saturday, 5 September 2015 at 01:43:43 UTC, Prudence wrote:Any ideas?See how vibe does it.
Sep 07 2015