mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-03-01 12:35:44 +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:
parent
2dc32f6ae4
commit
a90f2ca74f
@ -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
|
||||
|
@ -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>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>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>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>
|
||||
<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>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>
|
||||
int foo (int) __attribute__ ((__dllexport__));
|
||||
|
||||
int
|
||||
foo (int i)
|
||||
BOOL WINAPI ReadFile (HANDLE, PVOID, DWORD, PDWORD, LPOVERLAPPED);
|
||||
</screen>
|
||||
|
||||
<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>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>
|
||||
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) &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, &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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user