]> sourceware.org Git - newlib-cygwin.git/commitdiff
* gcc.xml (gcc-default: Rename from gcc-cons. Change title.
authorCorinna Vinschen <corinna@vinschen.de>
Thu, 25 Jul 2013 09:04:21 +0000 (09:04 +0000)
committerCorinna Vinschen <corinna@vinschen.de>
Thu, 25 Jul 2013 09:04:21 +0000 (09:04 +0000)
(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.

winsup/doc/ChangeLog
winsup/doc/gcc.xml

index 5fbe1be4f12d4f039bbbd7364de435c23a1c9119..bd4eeefa9380d9b5681bd3d243c692ca5975497b 100644 (file)
@@ -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
index b9039db96da406d4d89dcc0057fd1ccf62244f79..e158626386d6019929f2bca840385150360b3456 100644 (file)
@@ -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) &amp;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, &amp;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 &lt;windows.h&gt;
-
-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(&amp;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(&amp;msg, NULL, 0, 0)) 
-       {
-               TranslateMessage(&amp;msg);
-               DispatchMessage(&amp;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, &amp;ps);
-                       RECT rt;
-                       GetClientRect(hWnd, &amp;rt);
-                       DrawText(hdc, glpszText, strlen(glpszText), &amp;rt, DT_TOP | DT_LEFT);
-                       EndPaint(hWnd, &amp;ps);
-                       break;
-               case WM_DESTROY:
-                       PostQuitMessage(0);
-                       break;
-               default:
-                       return DefWindowProc(hWnd, message, wParam, lParam);
-       }
-       return 0;
-}
-</screen>
-</para>
-
 </sect2>
 </sect1>
This page took 0.038231 seconds and 5 git commands to generate.