Win32 example/tutorial with GC?

David Friedman dvdfrdmn at users.ess-eff.net
Tue May 1 18:36:40 PDT 2007


Johnny,

I had the main/WinMain call order backwards.  So, with the current 
distribution, I do not think it is possible to get the linker to 
automatically use whichever of main or WinMain is defined (like DMD does(?))

There is a simple workaround, however:  Use the following command to link.

gdc -o WinMenu-gdc.exe WinMenu.d -lmingw32

This will pull in MinGW's C main() that calls WinMain.  The

Also, you probably want to add -mwindows to the link command line so the 
.exe will not open a console when run.

David

Johnny wrote:
> David,
> 
> It's still not working with me; I must have something wrong in my code 
> or in my MinGW/GDC installation.
> 
> Here is a simple example that I tried to compile with GDC 0.23. I really 
> wish not only to correct the problem, but to understand exactly what's 
> going wrong:
> 
> 
> Compilation Steps:
> -----------------
> 1- $ gdc -c -v WinMenu.d  (OK)
> 
>     Reading specs from c:/MinGW/bin/../lib/gcc/mingw32/3.4.5/specs
>     Configured with: ../gcc-3.4.5-20060117-1/configure --prefix=/gdc 
> --disable-shared --enable-languages=c,d --host=mingw32 --target=mingw32 
> --with-gnu-ld --with-gnu-as --enable-threads --disable-nls 
> --disable-win32-registry --disable-shared --enable-sjlj-exceptions
>     Thread model: win32
>     gcc version 3.4.5 (mingw special) (gdc 0.23, using dmd 1.007)
>      c:/MinGW/bin/../libexec/gcc/mingw32/3.4.5/cc1d.exe WinMenu.d -quiet 
> -dumpbase WinMenu.d -auxbase WinMenu -version -iprefix 
> c:\MinGW\bin\../lib/gcc/mingw32/3.4.5/ -o 
> g:\DOCUME~1\ADMINI~1\LOCALS~1\Temp/ccoDaaaa.s
>     GNU D version 3.4.5 (mingw special) (gdc 0.23, using dmd 1.007) 
> (mingw32)
>             compiled by GNU C version 3.4.2 (mingw-special).
>     GGC heuristics: --param ggc-min-expand=46 --param 
> ggc-min-heapsize=31678
>      
> c:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../mingw32/bin/as.exe -o 
> WinMenu.o g:\DOCUME~1\ADMINI~1\LOCALS~1\Temp/ccoDaaaa.s
> 
> 
> 2- $ gdc -v -Wall -o  WinMenu-gdc.exe WinMenu.d -lgphobos  (Link errors)
> 
>     Reading specs from c:/MinGW/bin/../lib/gcc/mingw32/3.4.5/specs
>     Configured with: ../gcc-3.4.5-20060117-1/configure --prefix=/gdc 
> --disable-shared --enable-languages=c,d --host=mingw32 --target=mingw32 
> --with-gnu-ld --with-gnu-as --enable-threads --disable-nls 
> --disable-win32-registry --disable-shared --enable-sjlj-exceptions
>     Thread model: win32
>     gcc version 3.4.5 (mingw special) (gdc 0.23, using dmd 1.007)
>      c:/MinGW/bin/../libexec/gcc/mingw32/3.4.5/cc1d.exe WinMenu.d -quiet 
> -dumpbase WinMenu.d -auxbase WinMenu -Wall -version -iprefix 
> c:\MinGW\bin\../lib/gcc/mingw32/3.4.5/ -o 
> g:\DOCUME~1\ADMINI~1\LOCALS~1\Temp/ccQJaaaa.s
>     GNU D version 3.4.5 (mingw special) (gdc 0.23, using dmd 1.007) 
> (mingw32)
>             compiled by GNU C version 3.4.2 (mingw-special).
>     GGC heuristics: --param ggc-min-expand=46 --param 
> ggc-min-heapsize=31678
>      
> c:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../mingw32/bin/as.exe -o 
> g:\DOCUME~1\ADMINI~1\LOCALS~1\Temp/ccwjbaaa.o 
> g:\DOCUME~1\ADMINI~1\LOCALS~1\Temp/ccQJaaaa.s
>      c:/MinGW/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe -Bdynamic -o 
> WinMenu-gdc.exe /mingw/lib/crt2.o 
> c:/MinGW/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o 
> -Lc:/MinGW/bin/../lib/gcc/mingw32/3.4.5 -Lc:/MinGW/bin/../lib/gcc 
> -L/gdc/lib/gcc/mingw32/3.4.5 
> -Lc:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../mingw32/lib 
> -L/mingw/lib -Lc:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../.. 
> -L/gdc/lib/gcc/mingw32/3.4.5/../../.. 
> g:\DOCUME~1\ADMINI~1\LOCALS~1\Temp/ccwjbaaa.o -lgphobos -lgphobos 
> -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 
> -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt 
> c:/MinGW/bin/../lib/gcc/mingw32/3.4.5/crtend.o
>     /mingw/lib/libgphobos.a(cmain.o):(.text+0x19): undefined reference 
> to `_Dmain'
>     collect2: ld returned 1 exit status
> 
> 
> It seems that the Phobos library itself refers to _Dmain and linker 
> can't find it, so where is _Dmain, and why isn't it found?
> 
> 
> The source code file is attached.
> 
> Thanks
> john
> 
> 
> 
> David Friedman wrote:
>> Johnny wrote:
>>> Hello
>>>
>>> I'm trying to make a simple windows GUI application using D.
>>> First, I used DMD, and I suffered a lot due to it's OMF format. So I 
>>> decided
>>> to switch to GDC (with MinGW). But I still receive linking errors 
>>> related to
>>> Phobos :-(
>>>
>>> Are there any examples or tutorials that can help in this area? I.e. 
>>> ones
>>> that show how to set the GC correctly... There are such examples for 
>>> DMD,
>>> but I couldn't find similar examples for GDC... So any help?
>>>
>>> Thanks
>>> john
>>>
>>>
>>>
>>
>> If you are linking with other libraries, you may need to explicitly 
>> link against -lgphobos with that library early on the command line:
>>
>> gdc a.o b.o -lgphobos -lwsock32
>>
>> If you do not need a custom WinMain, just write the normal D main(). 
>> Otherwise, the easiest thing to do is call _d_run_Dmain:
>>
>> ---
>> import std.c.windows.windows;
>> extern (C) int _d_run_Dmain(int argc, char **argv);
>> extern (Windows)
>> int WinMain(HINSTANCE hInstance,
>>         HINSTANCE hPrevInstance,
>>         LPSTR lpCmdLine,
>>         int nCmdShow)
>> {
>>     char * fake_argv ="x";
>>     return _d_run_Dmain(1, & fake_argv);
>> }
>>
>> int main(char[][] args) {
>>   return 0;
>> }
>> ---
>>
>> David
> 
> 
> ------------------------------------------------------------------------
> 
> import std.c.windows.windows;
> import std.c.stdio;
> import std.string;
> 
> char[] Test_string="You selected Test menu item";
> char[] Hello_string="Hello, my friend";
> char[] Goodbye_string="See you again, bye";
> 
> HINSTANCE hInstance;
> 
> enum {
> 	IDM_TEST=1,
> 	IDM_HELLO,
> 	IDM_GOODBYE,
> 	IDM_EXIT
> }
> 
> 
> int doit() {
> 	hInstance = GetModuleHandleA(null);
> 	
> 	WNDCLASS wc;
> 
> 	wc.lpszClassName = "DWndClass";
> 	wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
> 	wc.lpfnWndProc = &WndProc;
> 	wc.hInstance = hInstance;
> 	wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
> 	wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_CROSS);
> 	wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
> 	wc.lpszMenuName = "TestMenu";
> 	wc.cbClsExtra = wc.cbWndExtra = 0;
> 	RegisterClassA(&wc);
> 	
> 	HWND hWnd;
> 	char[] sClass="My class 0";
> 	char[] sApp="My Application 0";
> 
> 	/+++++
> 	hWnd = CreateWindowA("DWndClass", "Just a window", WS_THICKFRAME |
> 		WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE,
> 		CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, HWND_DESKTOP,
> 		cast(HMENU) null, hInstance, null);
> 	+++++/
> 
> 	hWnd = CreateWindowA(toStringz(sClass), toStringz(sApp), WS_THICKFRAME |
> 		WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE,
> 		CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, HWND_DESKTOP,
> 		cast(HMENU) null, hInstance, null);
> 
> 	assert(hWnd);	
> 
> 	ShowWindow(hWnd,SW_SHOWNORMAL);
> 	UpdateWindow(hWnd);
> 
> 	MSG msg;
> 	while (GetMessageA(&msg, cast(HWND) null, 0, 0))
> 	{
> 		TranslateMessage(&msg);
> 		DispatchMessageA(&msg);
> 	}
> 	
> 	return 1;
> }//doit()
> 
> 
> /**********************************************************/
> 
> /* Note the similarity of this code to the console D startup
>  * code in \dmd\src\phobos\dmain2.d
>  * You'll also need a .def file with at least the following in it:
>  *	EXETYPE NT
>  *	SUBSYSTEM WINDOWS
>  */
> 
> 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;
> }
> 
> extern(Windows)
> {
> 	void DestroyWindow(HANDLE);
> }
> 
> extern(Windows)
> int WndProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam)
> {
> 	switch(uMsg)
> 	{
> 	case WM_DESTROY:
> 		PostQuitMessage(cast(int) null);
> 		break;
> 	case WM_COMMAND:
> 		switch (LOWORD(wParam))
> 		{
> 		case IDM_TEST:
> 			MessageBoxA(cast(HANDLE) null,"Test string","Menu test",MB_OK);
> 		case IDM_HELLO:
> 			MessageBoxA(cast(HANDLE) null,"Hello in D","Menu test",MB_OK);
> 			break;
> 		case IDM_GOODBYE:
> 			MessageBoxA(cast(HANDLE) null,"Goodbye in D","Menu test", MB_OK);
> 			break;
> 		default:
> 			DestroyWindow(hWnd);
> 		}//switch menu selection
> 		break;
> 	default:
> 		return DefWindowProcA(hWnd,uMsg,wParam,lParam);
> 	}//switch msg
> 	return 0;
> }//WndProc()
> 


More information about the D.gnu mailing list