4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-03-01 20:45:37 +08:00

* 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.
This commit is contained in:
Corinna Vinschen 2013-07-25 09:04:21 +00:00
parent 2dc32f6ae4
commit a90f2ca74f
2 changed files with 104 additions and 115 deletions

View 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> 2013-07-21 Corinna Vinschen <corinna@vinschen.de>
* new-features.sgml (ov-new1.7.22): Add GetCommandLine and regcomp * new-features.sgml (ov-new1.7.22): Add GetCommandLine and regcomp

View File

@ -4,11 +4,10 @@
<sect1 id="gcc"><title>Using GCC with Cygwin</title> <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. <para>Use gcc to compile, just like under UNIX. Refer to the GCC User's Guide
Refer to the GCC User's Guide for information on standard usage and for information on standard usage and options. Here's a simple example:</para>
options. Here's a simple example:</para>
<example id="gcc-hello-world"> <example id="gcc-hello-world">
<title>Building Hello World with GCC</title> <title>Building Hello World with GCC</title>
@ -23,29 +22,104 @@ Hello, World
</sect2> </sect2>
<sect2 id="gcc-gui"><title>GUI Mode Applications</title> <sect2 id="gcc-64"><title>Building applications for 64 bit Cygwin</title>
<para>Cygwin allows you to build programs with full access to the <para>The 64 bit Cygwin toolchain uses the
standard Windows 32-bit API, including the GUI functions as defined in <ulink url="http://en.wikipedia.org/wiki/X86_calling_convention#Microsoft_x64_calling_convention">Microsoft x64 calling convention</ulink>
any Microsoft or off-the-shelf publication. However, the process of by default, so you can create applications using the Win32 API just as with
building those applications is slightly different, as you'll be using the 32 bit Cygwin toolchain.</para>
the GNU tools instead of the Microsoft tools.</para>
<para>For the most part, your sources won't need to change at all. <para>There's just one important difference. The 64 bit Cygwin compilers use
However, you should remove all __export attributes from functions a different data model than the Mingw and Microsoft compilers. For reference,
and replace them like this:</para> 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>Here's an example. The Win32 function <function>ReadFile</function>
returns the number of read bytes via a pointer to a DWORD variable:</para>
<screen> <screen>
int foo (int) __attribute__ ((__dllexport__)); BOOL WINAPI ReadFile (HANDLE, PVOID, DWORD, PDWORD, LPOVERLAPPED);
int
foo (int i)
</screen> </screen>
<para>The Makefile is similar to any other UNIX-like Makefile, <para>Note that the forth parameter is a pointer to a DWORD, thus it's a
and like any other Cygwin makefile. The only difference is that you use pointer to a 4 byte type, on 32 as well as on 64 bit Windows. Now we write
<command>gcc -mwindows</command> to link your program into a GUI our own <function>my_read</function> function using ReadFile:</para>
application instead of a command-line application. Here's an example:</para>
<example id="gcc-64-ex1">
<title>64bit-programming, Using ReadFile, 1st try</title>
<screen>
ssize_t
my_read (int fd, void *buffer, size_t bytes_to_read)
{
HANDLE fh = _get_osfhandle (fd);
ssize_t bytes_read;
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>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> <screen>
<![CDATA[ <![CDATA[
@ -60,101 +134,8 @@ myapp.res : myapp.rc resource.h
<para>Note the use of <filename>windres</filename> to compile the <para>Note the use of <filename>windres</filename> to compile the
Windows resources into a COFF-format <filename>.res</filename> file. Windows resources into a COFF-format <filename>.res</filename> file.
That will include all the bitmaps, icons, and other resources you That will include all the bitmaps, icons, and other resources you
need, into one handy object file. Normally, if you omitted the "-O need, into one handy object file. For more information on
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
<filename>windres</filename>, consult the Binutils manual. </para> <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> </sect2>
</sect1> </sect1>