Win32 example/tutorial with GC?

Johnny johnnykiro at gmail.com
Fri May 4 03:21:47 PDT 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 at 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()
>>


More information about the D.gnu mailing list