Ide Indy Delphi

Title: Adventures in Kylix, Part III
Question: Digging the Hole Deeper
Answer:
Adventures in Kylix
Part Three: Digging the Hole Deeper
[This is kind of long because of sections that expain Unix topics for Windows
people. Sorry if this annoys people who just want the quick and dirty Kylix
facts.]
Pulled in another core library that exercises interfaces heavily; passed
with flying colours out of the box. Pulled in heavy XML manipulation
code. Passed with no errors or bugs. The bottom line is that generic code
ports 100% perfectly.
Ah... memory mapping. This is highly OS dependent code wrapped in an
OS-neutral interface. {$IFDEF LINUX} time, wrapping huge chunks
of code.
I got reminded on the ngs that Borland recommends
wrapping code with:
{$IFDEF MSWINDOWS}
// Windows-specific code
{$ENDIF}
{$IFDEF LINUX}
// Linux-specific code
{$ENDIF}
to allow for future platforms. John Kaster mentioned this during his
SLCDUG presentation. I forgot.
The only problem with this with respect to Delphi 5 is that MSWINDOWS
does not appear to be defined in Delphi 5. I added the following code to
the most basic common library in order to abate this:
{$IFNDEF MSWINDOWS}
{$IFDEF WIN32}
{$DEFINE MSWINDOWS}
{$ENDIF}
{$ENDIF}
I got additional information that is more involved.
Another suggestion was to add the following code to my implmentation
to guard against future OS collisions:
{$UNDEF CodeIsTested}
{$IDEF MSWINDOWS}
{$DEFINE CodeIsTested}
{$ENDIF}
{$IDEF LINUX}
{$DEFINE CodeIsTested}
{$ENDIF}
{$IFNDEF CodeIsTested}
{$MESSAGE ERROR 'Meeep! Test me!'}
{$ENDIF}
This seems very reasonable and is trivial to copy.
Awww... I got my first problem while compiling. Internal error: U2867
OK. I shut down Kylix, then loaded up the project again. I got "Internal
error: U2867" again. I commented the offending line out, recompiled, which
stopped at a syntax error after the offending line, then uncommented the
offending line, and it worked. I don't know if I like that. [Note: Reviewing
this document the next day, I've seen nothing else of the sort to date,
which is encouraging.]
Don't mark the following up as a Kylix problem yet.
Kylix actually locked up! I don't know whether this is a Kylix problem
or a Helix GNOME problem. I'm running a beta version of GNOME. Personally
I would bet it's the beta GNOME, as I have other apps do it infrequently.
(BTW, if you need for forcibly kill something, xkill will allow you
to click on a window and terminate the owning process. Depending on the
window manager, this may be available as a menu item or decoration.)
[start special topic "X"]
The terms window manager and decoration are foreign
to Windows programmers. This is a rough tutorial concluded by Kylix effects.
For Windows-bred people, the Un*x graphical user interface, X windows,
(known simply as "X") may seem a little strange. Microsoft has an inseparable
weld between the operating system and the windowing system. They
are inextricably intertwined. This forces people to do things the Microsoft
Way and no other. The Microsoft Way pretends to be multi-user, but the
tight weld between OS and GUI really forces people to use one machine per
person. This weld strongly colours user perception of what is "right" and
"wrong" with a GUI.
Un*x applies the client-server concept to the GUI, though at first blush
it looks backwards to most C/S programmers.
The X "server" is the machine with the graphics card, mouse, keyboard,
interacting with a (hopefully) warm body. A database server gives remote
access to a database. A web server gives remote access to HTML pages. An
X server gives remote access to a video card, mouse, and keyboard. (Seem
wierd? The cool part (IMHO) is coming.)
The X "client" is the application with a GUI. As with any client, it
connects to a server, fires off commands, and listens to responces. The
commands are generally graphical drawing commands, while the responces
are generally keyboard and mouse events.
This is similar to a database client application which connects to a
server, fires off database commands, and listens to database responces.
Now any good client-server architecture doesn't care whether the client
application and server reside on the same machine, or on different machines
with a network connection. X is a good C/S architecture. As an example:
I am responsible for maintaining a client's web server. It is running
Linux and resides outside of the client's firewall, sitting right on the
'Net. Physically it sits among the servers and racks at the client's building
in SLC. It runs headless, or without a monitor, keyboard, or mouse. I use
a secure telnet-like program called "ssh" (secure shell) to remotely log
into the machine across the InterNet. On the remote machine I can run a
configuration program that uses a GUI. X creates a connection between the
remote application and my Linux workstation at home. (By virtue of a little
ssh magic, this connection is encrypted.) The C/S architecture of X allows
me to then alter the configuration of the web server from home using a
nice GUI. The configuration application on the web server does not care
that I am sitting at my keyboard, mouse, and monitor thirty miles away,
were rather than in the machine's physical presence. It only cares that
it has a connection to an X server.
Besides being a client-sever architecture, X windows also separates
"specifcation" from "implementation." What this means in practice is that
The client program can state "I want a 600x400 window to be displayed"
and "display the following information in the window."
The server side will gladly comply, but not in a Windows fashion. The
window is merely a rectangular area on the screen. The title bar, edges
of the window, window placement, mouse focus, etc. are all outside of the
scope (or control in many cases) of both the client application and the
X server.
There are two other programs running, the windows manager and the font
server.
The X server does not know how to render fonts, but gets that information
the font server. The font server is normally on the same machine as the
X server, but does not have to be.
The windows manager handles the "look and feel" of the windows, and
to a degree the widgets
(controls). The title bar, window edges, etc. are called "decorations."
The window manager controls focus, stacking, etc. Some Un*x heads like
to be able to type in an active window that is partially hidden by an inactive
window in the foreground in certain situations. This freaks out some Windows
users. It's just not "right."
Window managers can be very light weight. I used to use a nice little
window manager called fvwm years ago
on a 486 with 16MB RAM. Linux and X windows were very responsive on that
machine -- much more responsive than Windows 3.1, let alone the Win32 monsters!
Desktop environments sit on top of window managers. The two most popular
in the Linux arena are GNOME and KDE.
KDE has a Windows-ish look and feel to it, making it popular among Windows
users. GNOME has a more Un*x tradition to it and is highly configurable,
sporting many themes. These themes go way beyond the Windows bland concept
of themes. One can make GNOME look and feel like Windows, a Macintosh,
a NeXT machine, or something from an alien spacecraft.
There are many great things about X, but the great flexibility sometimes
drives Windows users nuts. Things can appear to be "broken." In Kylix,
the BorderStyle "bsDialog" may not always behave "correctly" from a Windows
perspective. Borders are not part of the actual window like they are in
Win32, but are 'decorations' under the window manager's control. Depending
on the window manager and its user preferences, it is possible that the
window manager will not honour the bsDialog request that the form not be
resizable!
[end special topic "X"]
To continue on...
Created OS-neutral wrappers for some file operations that are handled
completely different in Win32 and Linux. POSIX support is great!
Note regarding working with Linux file operations:
If you're familiar with C, you'll remember that functions like fopen
return FILE* when successful. PIOFile is the Kylix redefinition
of FILE*. Thus the fopen in Libc
function fopen(FileName: PChar; Modes: PChar): PIOFile; cdecl;
directly maps to the C fopen function provided by glibc.
SERVICES
Under Unix, daemons
(an older, alternate spelling for "demon" from the Greek),
are the analogue to Windows NT services.
Creating a daemon is very very easy. Make a console app. That's it.
A daemon is nothing special. (Yeah!)
You'll probably want to create an entry for the init stuff. I'm not
going to detail that here, but it's just hacking together a text file.
I've typed enough about X that I don't want to explain the init stuff right
now.
DATABASE
OK, I'm into porting the database code. The code that I'm porting is
a set of database-neutral interfaces that wrap Interbase, Oracle, and ADO.
They are used for firing off discrete queries and stored procedures with
zero GUI interaction and minimum fuss on the part of the programmer.
The interfaces and abstract classes compile fine.
dbExpress
dbExpress is a thin, generic wrapper around a SQL database's drivers.
This is why it will not work with Paradox tables; no SQL database to talk
to.
There are several ways to set up database connectivity. The basic piece
is TSQLConnection. This currently wraps Interbase, Oracle, DB2, and MySQL
databases.
NOTE: dbExpress does not currently work with MySQL v3.32, but
works fine with v3.22.32. One fellow burned some dollars on
Borland tech support to figure this one out. (He reported that Borland
refunded the money. That's classy in this day and age.) Otherwise the application
segfaults
-- as a graceful Kylix excpetion instead of coring.
[start special topic "core dump"]
"Core
dump" is a term that shows the long history of Un*x, referring to RAM
as "core".
(Everybody who's seen ferrite core memory raise your hand. Those who've
worked on machines with core memory, raise your hand. Very good class.
We've just identified the computing dinosaurs in our midst. I'm not telling
how many times I raised my hand.)
A signal is a OS-generated notification sent to a process. Some signals
are benign, others not. The Linux kernel generates signals when certain
very bad events happen, such as attempting to address bad or illegal virtual
memory, a bus failure, an illegal CPU instruction, or something else that
really wigs the CPU out. Timer events are ofttimes triggered via
signals. Other signals are useful. For example, many daemons (services)
can be forced to re-read their configuration files by sending the process
a SIGHUP signal.
For example, if you try to dereference a nil pointer, the OS
traps the very bad event and "signals" to the process with SIGSEGV ("segment
violation", known in Windows as an "access violation"). If the process
doesn't handle the signal, the OS takes over again, and (depending on the
signal) the OS will abruptly terminate the process. Before it terminates
process, it will take a snapshot of the memory used by the program and
write it to disk in a file named 'core'. This process of copying the process'
RAM to disk is known as "dumping core".
It is possible to fire up a debugger, such as gdb, attach to the core
file, and do some post-mortem diagnostics. It's really quite handy,
much more graceful than Dr. Watson in many aspects.
So, how does Kylix handle signals? Very nicely. Kylix will trap
nasty signals and turn them into OS exceptions using the same mechanisms
found in Delphi. The details are pretty well documented in SysUtils. Kylix
cleverly tweaks the execution context's internals to make the Delphi exception
handler and stack unwinder work exactly as they do under Windows. There's
some fairly
heavy wizardry there, so only look if you've got your dispell magic
underwear on. (It's kind of cool how they do it, but I'm a
sad, strange little man. ;-)
For example, dereferencing a NULL pointer in C will cause the application
to core. (Die with a core dump.) However, under Kylix's debugger, one gets
an exception dialog that says "Project Project1 received signal SIGSEGV
(11). Process stopped. Use Step or Run to continue." This gets translated
into the familiar "Access violation at address 080B3844, accessing address
0000000".
If you run the program outside of the IDE, one simply sees the EAccessViolation
thrown.
[end special topic "core dump"]
On the dbExpress tab of the Kylix IDE, we see the following:
TSQLConnection
TSQLDataSet
TSQLQuery
TSQLStoredProc
TSQLTable
TSQLMonitor
TSQLClientDataSet
Playing with dbExpress, dbExpress seems to work only with unidirectional
cursors. TSQLClientDataSet is used to implement bidirectional scrolling.

Drop on a TSQLConnection, connect to database.
Drop on a TSQLQuery, select * from tablename.
Drop on a button, add the following code:
SQLQuery1.Next;
SQLQuery1.Prior;
Run the app, and the SQLQuery1.Next work fine. Prior bombs with "Operation
not allowed on a unidirectional dataset."
Nice little feature: Yesterday I set up a dummy project to do a
quick probe of the database functionality. I put a TSQLConnection on the
main form and attached it to the Interbase database on my Linux workstation.
Kylix remembered these settings and automatically fills them in for me.
I like this!

Drop on a TSQLClientDataSet,
CommandType defaults to ctQuery,
Set CommandText to "select * from tablename",
Replace the button event handler code with
SQLClientDataSet1.Next;
SQLClientDataSet1.Prior;
and lo, it works.
I'll run database regression tests tomorrow.
Version History:
2001-03-15:
Corrected misstatement that Kylix does not work with MySQL 3.22.32.
Thanks to Chris Pattinson for catching that big error!
Updated report on Borland tech support call.
Bert Garcia reminded me that desktop environments are not window managers.
Thanks for zinging me on that one!
Found link to my favourite Toy Story quote.
Copyright 2001 James
R. Knowles