Mega Code Archive

 
Categories / Delphi / Ide Indy
 

Adventures in Kylix, Part III

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