diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2013-07-25 09:04:21 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2013-07-25 09:04:21 +0000 |
commit | a90f2ca74f5effcd2dcb65e304c63a7ebe119408 (patch) | |
tree | 6fc6f8bcf0b50c741840b38708338719e2991f70 | |
parent | 2dc32f6ae4572352e086daec712b0299df5d6324 (diff) | |
download | newlib-a90f2ca74f5effcd2dcb65e304c63a7ebe119408.zip newlib-a90f2ca74f5effcd2dcb65e304c63a7ebe119408.tar.gz newlib-a90f2ca74f5effcd2dcb65e304c63a7ebe119408.tar.bz2 |
* gcc.xml (gcc-default: Rename from gcc-cons. Change title.
(gcc-64): New section explaininig differences in programming for
64 bit Cygwin.
(gcc-gui): Simplify description and aim at UNIX/Linux developers only.
Note that X programming is preferred. Drop example.
-rw-r--r-- | winsup/doc/ChangeLog | 8 | ||||
-rw-r--r-- | winsup/doc/gcc.xml | 209 |
2 files changed, 103 insertions, 114 deletions
diff --git a/winsup/doc/ChangeLog b/winsup/doc/ChangeLog index 5fbe1be..bd4eeef 100644 --- a/winsup/doc/ChangeLog +++ b/winsup/doc/ChangeLog @@ -1,3 +1,11 @@ +2013-07-25 Corinna Vinschen <corinna@vinschen.de> + + * gcc.xml (gcc-default: Rename from gcc-cons. Change title. + (gcc-64): New section explaininig differences in programming for + 64 bit Cygwin. + (gcc-gui): Simplify description and aim at UNIX/Linux developers only. + Note that X programming is preferred. Drop example. + 2013-07-21 Corinna Vinschen <corinna@vinschen.de> * new-features.sgml (ov-new1.7.22): Add GetCommandLine and regcomp diff --git a/winsup/doc/gcc.xml b/winsup/doc/gcc.xml index b9039db..e158626 100644 --- a/winsup/doc/gcc.xml +++ b/winsup/doc/gcc.xml @@ -4,11 +4,10 @@ <sect1 id="gcc"><title>Using GCC with Cygwin</title> -<sect2 id="gcc-cons"><title>Console Mode Applications</title> +<sect2 id="gcc-default"><title>Standard Usage</title> -<para>Use gcc to compile, just like under UNIX. -Refer to the GCC User's Guide for information on standard usage and -options. Here's a simple example:</para> +<para>Use gcc to compile, just like under UNIX. Refer to the GCC User's Guide +for information on standard usage and options. Here's a simple example:</para> <example id="gcc-hello-world"> <title>Building Hello World with GCC</title> @@ -23,29 +22,104 @@ Hello, World </sect2> -<sect2 id="gcc-gui"><title>GUI Mode Applications</title> +<sect2 id="gcc-64"><title>Building applications for 64 bit Cygwin</title> + +<para>The 64 bit Cygwin toolchain uses the +<ulink url="http://en.wikipedia.org/wiki/X86_calling_convention#Microsoft_x64_calling_convention">Microsoft x64 calling convention</ulink> +by default, so you can create applications using the Win32 API just as with +the 32 bit Cygwin toolchain.</para> + +<para>There's just one important difference. The 64 bit Cygwin compilers use +a different data model than the Mingw and Microsoft compilers. For reference, +see the Wikipedia entry on +<ulink url="http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models">64-bit computing</ulink>.</para> + +<para>While the Mingw and Microsoft compilers use the <literal>LLP64</literal> +data model, Cygwin compilers use the <literal>LP64</literal> data model, just +like Linux. This affects the size of the type <literal>long</literal>. In the +<literal>LLP64</literal> model preferred by Microsoft, +<function>sizeof(long)</function> is 4. This applies for the related Win32 +types like <literal>LONG</literal>, <literal>ULONG</literal>, +<literal>DWORD</literal>, etc., too.</para> + +<para>In the <literal>LP64</literal> model used by Cygwin, <function>sizeof(long)</function> is 8, +just like the size of pointers or the types <literal>size_t/ssize_t</literal>. +This simplifies porting Linux applications to 64 bit Cygwin, but it requires +due diligence when calling Windows functions taking LONG, ULONG, DWORD, or any +other equivalent type. This is especially important in conjunction with +pointers.</para> -<para>Cygwin allows you to build programs with full access to the -standard Windows 32-bit API, including the GUI functions as defined in -any Microsoft or off-the-shelf publication. However, the process of -building those applications is slightly different, as you'll be using -the GNU tools instead of the Microsoft tools.</para> +<para>Here's an example. The Win32 function <function>ReadFile</function> +returns the number of read bytes via a pointer to a DWORD variable:</para> -<para>For the most part, your sources won't need to change at all. -However, you should remove all __export attributes from functions -and replace them like this:</para> +<screen> +BOOL WINAPI ReadFile (HANDLE, PVOID, DWORD, PDWORD, LPOVERLAPPED); +</screen> + +<para>Note that the forth parameter is a pointer to a DWORD, thus it's a +pointer to a 4 byte type, on 32 as well as on 64 bit Windows. Now we write +our own <function>my_read</function> function using ReadFile:</para> +<example id="gcc-64-ex1"> +<title>64bit-programming, Using ReadFile, 1st try</title> <screen> -int foo (int) __attribute__ ((__dllexport__)); +ssize_t +my_read (int fd, void *buffer, size_t bytes_to_read) +{ + HANDLE fh = _get_osfhandle (fd); + ssize_t bytes_read; -int -foo (int i) + if (ReadFile (fh, buffer, bytes_to_read, (PDWORD) &bytes_read, NULL)) + return bytes_read; + set_errno_from_get_last_error (); + return -1; +} </screen> +</example> + +<para>While this example code works fine on 32 bit Windows, it has in fact +a bad bug. The assumption that the size of ssize_t is the same as the size +of DWORD is wrong for 64 bit. In fact, since +<function>sizeof(ssize_t)</function> is 8, <function>ReadFile</function> +will write the number of read bytes into the upper 4 bytes of the variable +<literal>bytes_read</literal>. <function>my_read</function> will +return the wrong number of read bytes to the caller.</para> -<para>The Makefile is similar to any other UNIX-like Makefile, -and like any other Cygwin makefile. The only difference is that you use -<command>gcc -mwindows</command> to link your program into a GUI -application instead of a command-line application. Here's an example:</para> +<para>Here's the fixed version of <function>my_read</function>:</para> + +<example id="gcc-64-ex2"> +<title>64bit-programming, Using ReadFile, 2nd try</title> +<screen> +ssize_t +my_read (int fd, void *buffer, size_t bytes_to_read) +{ + HANDLE fh = _get_osfhandle (fd); + DWORD bytes_read; + + if (ReadFile (fh, buffer, bytes_to_read, &bytes_read, NULL)) + return bytes_read; + set_errno_from_get_last_error (); + return -1; +} +</screen> +</example> + +</sect2> + +<sect2 id="gcc-gui"><title>GUI Mode Applications</title> + +<para>Cygwin comes with an X server, so usually you should compile your +GUI applications as X applications to allow better interoperability with +other Cygwin GUI applications.</para> + +<para>Other than that, Cygwin allows you to build programs with full access +to the standard Windows API, including the GUI functions as defined in +any Microsoft or off-the-shelf publication.</para> + +<para>The build process is similar to any other build process. The only +difference is that you use <command>gcc -mwindows</command> to link your +program into a GUI application instead of a command-line application. +Here's an example Makefile:</para> <screen> <![CDATA[ @@ -60,101 +134,8 @@ myapp.res : myapp.rc resource.h <para>Note the use of <filename>windres</filename> to compile the Windows resources into a COFF-format <filename>.res</filename> file. That will include all the bitmaps, icons, and other resources you -need, into one handy object file. Normally, if you omitted the "-O -coff" it would create a Windows <filename>.res</filename> format file, -but we can only link COFF objects. So, we tell -<filename>windres</filename> to produce a COFF object, but for -compatibility with the many examples that assume your linker can -handle Windows resource files directly, we maintain the -<filename>.res</filename> naming convention. For more information on +need, into one handy object file. For more information on <filename>windres</filename>, consult the Binutils manual. </para> -<para> -The following is a simple GUI-mode "Hello, World!" program to help -get you started: -<screen> -/*-------------------------------------------------*/ -/* hellogui.c - gui hello world */ -/* build: gcc -mwindows hellogui.c -o hellogui.exe */ -/*-------------------------------------------------*/ -#include <windows.h> - -char glpszText[1024]; - -LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); - -int APIENTRY WinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nCmdShow) -{ - sprintf(glpszText, - "Hello World\nGetCommandLine(): [%s]\n" - "WinMain lpCmdLine: [%s]\n", - lpCmdLine, GetCommandLine() ); - - WNDCLASSEX wcex; - - wcex.cbSize = sizeof(wcex); - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = WndProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = hInstance; - wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wcex.hCursor = LoadCursor(NULL, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcex.lpszMenuName = NULL; - wcex.lpszClassName = "HELLO"; - wcex.hIconSm = NULL; - - if (!RegisterClassEx(&wcex)) - return FALSE; - - HWND hWnd; - hWnd = CreateWindow("HELLO", "Hello", WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); - - if (!hWnd) - return FALSE; - - ShowWindow(hWnd, nCmdShow); - UpdateWindow(hWnd); - - MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - return msg.wParam; -} - -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - PAINTSTRUCT ps; - HDC hdc; - - switch (message) - { - case WM_PAINT: - hdc = BeginPaint(hWnd, &ps); - RECT rt; - GetClientRect(hWnd, &rt); - DrawText(hdc, glpszText, strlen(glpszText), &rt, DT_TOP | DT_LEFT); - EndPaint(hWnd, &ps); - break; - case WM_DESTROY: - PostQuitMessage(0); - break; - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } - return 0; -} -</screen> -</para> - </sect2> </sect1> |