Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

WinMain in Tango

Moderators: larsivi kris

Posted: 09/21/07 13:09:28

Hi I am going to write a Win GUI toolkit, (using Tango of course) I guess, I have to modify the Phobos code a bit. Sorry, I have not found something within the WIKI.

extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleUnitTests();

extern (Windows)
int WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow)
{
    int result;

    gc_init();			// initialize garbage collector
    _minit();			// initialize module constructor table

    try
    {
	_moduleCtor();		// call module constructors
	_moduleUnitTests();	// run unit tests (optional)

	result = doit();	// insert user code here
    }

    catch (Object o)		// catch any uncaught exceptions
    {
	MessageBoxA(null, cast(char *)o.toString(), "Error",
		    MB_OK | MB_ICONEXCLAMATION);
	result = 0;		// failed
    }

    gc_term();			// run finalizers; terminate garbage collector
    return result;
}

So folks, how do I define an adequate Tango WinMain? function... Many Thanks in advance, Bjoern

Author Message

Posted: 09/21/07 14:20:53 -- Modified: 09/21/07 14:27:54 by
sean

Before you do that, I know Bud has some way to turn any app into a Windows app by simply dropping in a .ref file (I believe). I'd look into that approach first. If it is insufficient, the easiest thing to do would be something like this:

extern (Windows) void*   LocalFree(void*);
extern (Windows) char*   GetCommandLineA();
extern (Windows) char**  CommandLineToArgvA(char*, int*);

extern (C) int main(int,char**);

extern (Windows)
int WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpCmdLine,
            int nCmdShow)
{
    char*  cbuf = GetCommandLineA();
    int    argc = 0;
    char** argv = CommandLineToArgvA(cbuf, &argc);

    int ret = main( argc, argv );
    LocalFree( argv );
    return ret;
}

And just link it into your app, then use D main, etc, as you normally would.

Oh, if you really want to trap any unhandled exceptions, you may want to call rt_init() and rt_term() instead, and simply call D main manually. Otherwise, the C main routine above will trap them and you'll never see them. You'd want to do something like this:

extern (C) void rt_init( void delegate(Exception) dg = null );
extern (C) void rt_term( void delegate(Exception) dg = null );

int main(char[][] args);

extern (Windows)
int WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpCmdLine,
            int nCmdShow)
{
    rt_init();
    try
    {
        // generate char[][] args;

        main( args );
    }
    catch( Exception e )
    {
    }
    catch( Object o )
    {
    }
    rt_term(); 
}

rt_init() and rt_term() exist to allow the creation of DLLs without having to know the actual runtime initialization and termination process, but they would work just as well for a Windows app.

Posted: 09/21/07 16:37:39

If you don't need hInstance or nCmdShow you can just use main() and compile with -L/SUBSYSTEM:WINDOWS:

import tango.io.Stdout;

void main()
{
	Stdout("Hello, world!");
}
dmd -L/SUBSYSTEM:WINDOWS hello.d

The resulting executable won't show the console window.

Posted: 04/14/08 10:42:56

hInstance can get by GetModuleHandle() function with parameter NULL:

HINSTANCE hInstance=GetModuleHandle(NULL);