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