By
Adam Skutt (mailto:askutt@wnec.edu),
Andrew Forgue (mailto:syndicate@arslinux.com)
You've probably heard of .NET, and since you're reading a Linux column, you've
probably also heard of the
Mono Project (http://www.mono-project.com/),
which provides a
NET (http://arstechnica.com/paedia/n/net/net-1.html)
compatible development platform. Mono has been the cause of a number of
discussions regarding copyright, software patents, and other legal issues. So,
instead of boring you with political ranting, we're going to concentrate on
Mono's technical merits (of which there are many) and show you how you can use
it for development. We also present ndiswrapper, which allows you to use some
Windows network drivers with Linux, this enabling you to use a number of
previously unsupported network cards.
We'll start out by introducing you to Mono (very briefly because you've probably
had this pounded down your throat for the past 2 years) then we'll present some
code and screenshots that demonstrate the versatility of the Mono project.
A brief history of Mono
The Mono project was conceived in the Summer of 2001 as an Open Source
alternative to Microsoft's .NET development platform. Since then, it has come
all the way to a 1.0 release among a flurry of controversy from mostly inside
the Open Source community itself. Although we will not outline the reasons here,
most of the criticism stems from the fact that .NET is Microsoft, and "we" don't
like them.
At the end of June, 2004, Mono released their first major version (1.0) and the
platform (especially C#) seems to be catching on very quickly. There's already a
music player (http://muine.gooeylinux.org/),
a new app called
Dashboard (http://www.nat.org/dashboard/),
an app I'm writing called
MonoPlanet (http://ahab.arslinux.com/svn/MonoPlanet/),
and not to mention an IDE for developing Mono Apps called
MonoDevelop (http://www.monodevelop.com/)
and
much more (http://www.nullenvoid.com/gtksharp/wiki/index.php/SoftWare).
For users?
A user of a platform that supports Mono will hopefully see better-quality
applications, applications that can just be installed (no compiling, not even
for packaging), and applications that are secure. The ease for developers (given
the proper tools) to write Mono applications will help to bring better
applications to Linux (just as soon as Gtk# supports the current Gtk+ library).
Linux advocates have been saying all along that application support is key to
its success. With the adoption of Mono, the accuracy of that statement should
soon become clear.
For developers?
Mono's main pull for developers is that it is cross-platform and makes writing
applications very fast because of its extensive framework. Mono also has the
concept of
garbage collection (http://en.wikipedia.org/wiki/Automatic_garbage_collection).
Gone are the days of using malloc() and free() and recording where you allocated
memory and making sure you free() it. Java has GC as well, but Java never really
caught on as an application language.
Here we will show you how to write a very basic cross-platform application and
run it on Windows and Linux. So without further delay, on to the code.
Note: Mono support in Mac OSX is still immature compared to other platforms, we
expect this to change now that 1.0 is out the door.
The code: example 1
This code is simple, it takes command line argument and prompts the user for a
Regular Expression. It test the command line string against the regular
expression and prints whether it succeeded or failed.
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace Volume_27
{
///
/// Linux.Ars Volume 27 Example 1
///
class Example1
{
static void Main (string[] args)
{
if( args.Length == 0 )
{
Usage();
Console.ReadLine();
return;
}
String input = "";
for(int i = 0; i < args.Length; i++)
input = input + ((i==0)?"":" ") + args[i];
Console.Write
("Enter a regular expression to test the string \"{0}\": ", input);
String regex = Console.ReadLine();
bool matches = Regex.IsMatch( input, regex );
Console.WriteLine
("\"{0}\" DOES {1} Match \"{2}\"", input, (matches)?"":"NOT", regex);
}
public static void Usage()
{
String ExecPath = Environment.GetCommandLineArgs()[0];
String Executable =
ExecPath.Substring(ExecPath.LastIndexOf(Path.DirectorySeparatorChar) + 1);
Console.WriteLine("-------------------------------------------------");
Console.WriteLine("{0} usage:", Executable );
Console.WriteLine();
Console.WriteLine("\t{0} [Input String]", Executable);
Console.WriteLine();
Console.WriteLine
("\t[Input String]: An input string that should be tested against");
Console.WriteLine("\t the prompted regular expression");
Console.WriteLine();
Console.WriteLine("-------------------------------------------------");
}
}
}
Download the compiled binary:
Here (http://www.arslinux.com/viewcvs.cgi/*checkout*/linux.ars/v27e1.exe)
As you can see, the actual meat of this application is seven lines of
code. Now, when we run this (on windows) we get this output:
C:\>md5sum v27e1.exe
492f501af39a990a873a008adf82e8c7 *v27e1.exe
C:\>v27e1 Linux.Ars is cool
Enter a regular expression to test the string "Linux.Ars is cool": ^L.*\.A*
"Linux.Ars is cool" DOES Match "^L.*\.A*"
And now to execute the same exact binary on Linux (the case-mismatch is
intentional)
forgue@ahab:~$ md5sum v27e1.exe
492f501af39a990a873a008adf82e8c7 v27e1.exe
forgue@ahab:~$
forgue@ahab:~$ ./v27e1.exe Linux.Ars is cool
Enter a regular expression to test the string "Linux.Ars is cool": ^L.*\.C*
"Linux.Ars is cool" DOES Match "^L.*\.C*"
The great power of Mono and .NET lies in the ONE line of code:
bool matches = Regex.IsMatch( input, regex );
.NET and Mono are actually a collection of libraries that form a framework which
allows you, the programmer, to write the logic of your application. I can call
one line of code to do input validation on a string which saves you
possibly hours of time. Things like Input validation, network communication,
file reading and writing, text encoding, regular expressions, formatting, XML
Parsing, LDAP Access, remoting, and GUI development are reduced to just a few
lines of code compared to possibly hundreds.
Next we'll demonstrate development of a Gtk# application that runs on both Linux
and Windows. Using the brand new MonoDevelop, this makes it fairly quick. We'll
do the same application, with two textboxes, and it will update the result label
in real time (each character you type will verify the regex).
So lets open MonoDevelop and start a new Gtk# project, call it whatever you
want. After the project is created you'll see a MyWindow.cs: open that and
replace everything with the below code:
using System;
using Gtk;
using System.Text;
using System.Text.RegularExpressions;
public class MyWindow : Window {
private VBox vBox;
private HBox hbox1;
private HBox hbox2;
private HBox hbox3;
private Entry txtInput;
private Entry txtRegex;
private Entry txtResult;
private Label lblLeft1;
private Label lblLeft2;
private Label lblLeft3;
public MyWindow () : base ("Linux.ars")
{
this.SetDefaultSize (400, 300);
this.DeleteEvent += new DeleteEventHandler (OnMyWindowDelete);
/* Create a vertical panel, each with horizontal panels,*/
/* the left side is the label and the right side is the textbox */
vBox = new VBox(false, 3);
hbox1 = new HBox(false, 2);
hbox2 = new HBox(false, 2);
hbox3 = new HBox(false, 2);
txtInput = new Entry();
txtRegex = new Entry();
txtResult = new Entry();
lblLeft1 = new Label();
lblLeft2 = new Label();
lblLeft3 = new Label();
// Disable editing of the result box
txtResult.Editable = false;
// If anything changes in the text boxes,
// call this function (These are event handler delegates)
txtRegex.Changed += new EventHandler(ChangedSomething);
txtInput.Changed += new EventHandler(ChangedSomething);
// Set the text of the labels on the left
lblLeft1.Text = "Input String:";
lblLeft2.Text = "Regular Expression:";
lblLeft3.Text = "Result:";
// Make them the same size
lblLeft1.SetSizeRequest(150, 20);
lblLeft2.SetSizeRequest(150, 20);
lblLeft3.SetSizeRequest(150, 20);
// Align the text to the right
lblLeft1.SetAlignment( 1, (float)0.5 );
lblLeft2.SetAlignment( 1, (float)0.5 );
lblLeft3.SetAlignment( 1, (float)0.5 );
// Now we add the controls to the panels
hbox1.PackStart(lblLeft1, true, true, 6);
hbox1.PackEnd(txtInput, true, true, 6);
hbox2.PackStart(lblLeft2, true, true, 6);
hbox2.PackEnd(txtRegex, true, true, 6);
hbox3.PackStart(lblLeft3, true, true, 6);
hbox3.PackEnd(txtResult, true, true, 6);
vBox.PackStart(hbox1, true, true, 0);
vBox.PackStart(hbox2, true, true, 0);
vBox.PackStart(hbox3, true, true, 0);
// Set the window characteristics
this.SetDefaultSize( 250, 80 );
this.Resizable = false;
this.BorderWidth = 10;
// Add the whole shebang to the window
this.Add( vBox );
// Show everything
this.ShowAll ();
}
void OnMyWindowDelete (object o, DeleteEventArgs args)
{
Application.Quit ();
}
void ChangedSomething(object o, EventArgs e)
{
// Get the text from the boxes
// (this gets called after it's updated)
String Input = txtInput.Text;
String RegEx = txtRegex.Text;
try
{
if( Regex.IsMatch(Input,RegEx) )
txtResult.Text = "Matches";
else
txtResult.Text = "Does Not Match";
}
catch(System.ArgumentException ae)
{
txtResult.Text = "Invalid Regular Expression";
}
}
}
Download the compiled binary:
Here (http://www.arslinux.com/viewcvs.cgi/*checkout*/linux.ars/v27e2.exe)
The above code, should produce the result below (on Linux):
Missing Picture
This article is in need of attention.
Please improve it and then remove this notice.
And on Windows:
Missing Picture
This article is in need of attention.
Please improve it and then remove this notice.
Conclusion
As you can clearly see, Mono brings almost limitless possibilities in breaking
down the barrier between desktops: a commercial software provider would target
Mono and it would "just work" on all platforms that Mono supported. How is this
different from Java? In my opinion Java makes things harder than it needs to be.
For starters, enforced exception handling can't auto-box/unbox primitive types
and doesn't support arbitrary length parameter lists String.Format() style.
The framework of Mono provides the ability to make a very tedious task in C/C++
almost trivial in C#. As the above example, RegEx, shows, it helps the
programmer concentrate on the program itself, rather than the logic supporting
the code.
Ndiswrapper (http://ndiswrapper.sourceforge.net/)
is a kernel module and set of userspace tools that let you use Windows network
drivers on your Linux machine. NDIS stands for Network Driver Interface
Specification, and it is the API used by Windows developers to write drivers for
network cards, including wireless network cards. Ndiswrapper is specifically
targeted for running cards that use newer 802.11g chipsets that do not have
Linux drivers, including the chipsets by Broadcom, Atheros, and Intel (
see the completely supported
list here (http://ndiswrapper.sourceforge.net/supported_chipsets.html))
including native drivers for some chipsets.
Using ndiswrapper is as simple as installing the tools, compiling support for
your kernel, and then loading the Windows driver. It appears tolLinux as a
regular wireless interface, and can be configured with the
normal wireless-tools (http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html).
For those who use with laptops that have unsupported chipsets, ndiswrapper is a
useful way to allow you to make fuller use of your machines. I personally have
excellent results with it on my Fujitsu E4100D, which uses a Broadcom 94306
chipset.
Not familiar with wireless in Linux at all? Don't worry, IBM has
you covered (http://www-106.ibm.com/developerworks/wireless/library/wi-run.html?ca=dgr-lnxw04WirelessTools4Lnx).