Thread overview
Win32 example/tutorial with GC?
May 01, 2007
Johnny
May 01, 2007
David Friedman
May 01, 2007
Johnny
May 01, 2007
Frits van Bommel
May 01, 2007
Johnny
May 02, 2007
David Friedman
May 04, 2007
Johnny
May 09, 2007
Dejan Lekic
May 01, 2007
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



May 01, 2007
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
May 01, 2007
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



May 01, 2007
Johnny wrote:
> 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?

"_Dmain" is how the "main" of your program normally gets renamed ("mangled") by the D compiler. It's not found because you didn't write one :).
What happens if you add an empty "void main() {}" ?

I'm pretty sure the Windows version of DMD (or perhaps optlink) will automatically use WinMain instead of main if it sees it, but I'm not sure about GDC/MinGW. Maybe some special command-line option needs to be passed?
May 01, 2007
Hi Frits

I added the empty main() and the linking succeeds, however, the program does nothing since the entry point (main() )  returns immediately (which is expected.
So may be the good question is how to make GDC accept WinMain as an entry point for Windows GUI programs.

Strangely, I have another simpler GUI program that links correctly with WinMain:

import win32.winbase;
import win32.windef;
import win32.winuser;

extern(Windows) int WinMain(HINSTANCE hInstance,
                        HINSTANCE hPrevInstance,
                        PSTR szCmdLine,
                        int iCmdShow)
{
      MessageBoxA(null, "Hello", "Hello Demo", MB_OK);
      return (0);
}


- Here is how I compile it:

	Administrator@home /cygdrive/c/D-Projects/gdc-test
	$ gdc -c gdctestwin.d -I"C:\dmd"


- Attempting to link with GDC fails:

	Administrator@home /cygdrive/c/D-Projects/gdc-test
	$ gdc -o gdctestwin.exe  gdctestwin.o
	/mingw/lib/libgphobos.a(cmain.o):(.text+0x19): undefined 	reference to `_Dmain'
	collect2: ld returned 1 exit status


- Linking with GCC sycceeds:

	Administrator@home /cygdrive/c/D-Projects/gdc-test
	$ gcc -o gdctestwin.exe  gdctestwin.o


- I tried to use GCC for linking my 1st example, but I get other errors:

	$ gcc -Wall -o WinMenu-gdc.exe WinMenu.o
	WinMenu.o:WinMenu.d:(.text+0xe7): undefined reference to `_D3std6string9toStringzFAaZPa'
	WinMenu.o:WinMenu.d:(.text+0xfb): undefined reference to `_D3std6string9toStringzFAaZPa'
	WinMenu.o:WinMenu.d:(.text+0x152): undefined reference to `CreateWindowA@44'
	WinMenu.o:WinMenu.d:(.text+0x17e): undefined reference to `_d_assert'
	WinMenu.o:WinMenu.d:(.text+0x269): undefined reference to `LOWORD@4'
	WinMenu.o:WinMenu.d:(.text+0x35a): undefined reference to 	`_Dmodule_ref'
	WinMenu.o:WinMenu.d:(.text+0x365): undefined reference to `_Dmodule_ref'
	WinMenu.o:WinMenu.d:(.data+0x48): undefined reference to `_D3std6string12__ModuleInfoZ'
	 WinMenu.o:WinMenu.d:(.data$_D31TypeInfo_E7WinMenu11__anonymous6__initZ[__D31TypeInfo_E7WinMenu11__anonymous6__initZ]+0x0): 	undefined reference to `_D13TypeInfo_Enum6__vtblZ'
WinMenu.o:WinMenu.d:(.data$_D31TypeInfo_E7WinMenu11__anonymous6__initZ[__D31TypeInfo_E7WinMenu11__anonymous6__initZ]+0x8): 	undefined reference to `_D10TypeInfo_i6__initZ'
	collect2: ld returned 1 exit status

- And here I added Phobos, but I get 1st error:

	$ gcc -Wall -o WinMenu-gdc.exe WinMenu.o -lgphobos
	/mingw/lib/libgphobos.a(cmain.o):(.text+0x19): undefined reference to `_Dmain'
	collect2: ld returned 1 exit status

So I'm confused :-( .. what are the definitive steps to compile and link a Windows GUI program using GDC/MinGW?

Regards,
john


Frits van Bommel wrote:
> Johnny wrote:
>> 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?
> 
> "_Dmain" is how the "main" of your program normally gets renamed ("mangled") by the D compiler. It's not found because you didn't write one :).
> What happens if you add an empty "void main() {}" ?
> 
> I'm pretty sure the Windows version of DMD (or perhaps optlink) will automatically use WinMain instead of main if it sees it, but I'm not sure about GDC/MinGW. Maybe some special command-line option needs to be passed?
May 02, 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()
> 
May 04, 2007
Hello David

I didn't know how exactly to change the code in order to add the mingw32 lib (-lmingw32), so I tried a different way:

	void main()
	{
	        int exit_code=WinMain(GetModuleHandle(null),null,GetCommandLineA(),SW_SHOWDEFAULT);
	        ExitProcess(exit_code);
	}

	extern (Windows) int WinMain(HINSTANCE hInstance,
	        HINSTANCE hPrevInstance,
	        LPSTR lpCmdLine,
	        int nCmdShow)
	{
	    uint result;
	    result = CMDIApp.MdiWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
	    return result;
	}


Now I have these errors:

$ ./build-gdc.sh
Compiling resources file (mdiapp.rc)..
Compiling main.d..
Linking to libraries..
main.o:main.d:(.text+0x80): undefined reference to `_D6mdiapp7CMDIApp10MdiWinMainWT5win325winnt6HANDLET5win325winnt6HANDLEPaiZk@16'
main.o:main.d:(.data+0x30): undefined reference to `_D6mdiapp12__ModuleInfoZ'
collect2: ld returned 1 exit status

I'll try to figure out the reason of these errors (any hint?).

Thanks
John



David Friedman wrote:
> 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()
>>
May 09, 2007
Johnny, have you tried the last compile/link command David wrote? I think it will successfully compile/link your application.