<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TuxTips</title>
	<atom:link href="http://www.tuxtips.org/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.tuxtips.org</link>
	<description>Linux Tips and Screencasts</description>
	<lastBuildDate>Mon, 18 Aug 2008 05:21:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Quick Thoughts on the Stackoverflow Beta</title>
		<link>http://www.tuxtips.org/?p=15</link>
		<comments>http://www.tuxtips.org/?p=15#comments</comments>
		<pubDate>Mon, 18 Aug 2008 05:21:06 +0000</pubDate>
		<dc:creator>codeninja</dc:creator>
				<category><![CDATA[Tuxtips]]></category>

		<guid isPermaLink="false">http://www.tuxtips.org/?p=15</guid>
		<description><![CDATA[I just got my invite a couple of days ago to the beta of Stack Overflow.  I&#8217;ll save an in-depth review for once the site has officially launched, but I just thought I would write a quick post to say that so far I&#8217;m pretty impressed.  The site is fast and well designed, [...]]]></description>
			<content:encoded><![CDATA[<p>I just got my invite a couple of days ago to the beta of Stack Overflow.  I&#8217;ll save an in-depth review for once the site has officially launched, but I just thought I would write a quick post to say that so far I&#8217;m pretty impressed.  The site is fast and well designed, and I&#8217;ve not run into any major bugs yet.  The community seems to be solid (although not as many linux systems developers as I&#8217;d like to see) and the reputation system seems like it&#8217;s well designed.  This looks like it could turn out to be another good site for programmers.  I&#8217;ll be sure to make a post here once the site goes live, and in the mean time if any of you are already in the beta, my username is CodeninjaTim, so be sure to keep an eye out for me.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tuxtips.org/?feed=rss2&amp;p=15</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Journey to Python Part 2: Input, Output, and Documentation</title>
		<link>http://www.tuxtips.org/?p=14</link>
		<comments>http://www.tuxtips.org/?p=14#comments</comments>
		<pubDate>Mon, 18 Aug 2008 05:16:41 +0000</pubDate>
		<dc:creator>codeninja</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.tuxtips.org/?p=14</guid>
		<description><![CDATA[In the last article in the Journey to Python series, I had gotten as far as doing some basic math, and displaying some data to the screen.  Over the last few days I&#8217;ve been working on two new facets of Python which will hopefully allow me to get up to speed in writing programs [...]]]></description>
			<content:encoded><![CDATA[<p>In the last article in the Journey to Python series, I had gotten as far as doing some basic math, and displaying some data to the screen.  Over the last few days I&#8217;ve been working on two new facets of Python which will hopefully allow me to get up to speed in writing programs that are actually useful.  This week I&#8217;ve played around a bit with reading input from the command line in a python program, as well as interacting with the operating system with the OS library; I&#8217;ve also had a chance to look at pydoc to get some documentation, and as per a reader request I&#8217;ve spent a bit of time thinking about pythons type system, and how it compares to more strict type systems in languages such as C++ and Java.<br />
<span id="more-14"></span></p>
<p>The first thing I would like to mention in todays article is something that struck me as I was writing a bit of python code earlier this evening.  For all of the (friendly and otherwise) jabs that the Python and Perl folks exchange, the more I work with python, I notice that there are a lot of small things that make it feel a little bit like perl to me.  To some people, this might seem like an insult, but the truth is I quite like perl, and I mean the comparison as a sincere compliment.  I imagine that a fair bit of this similarity is just in the fact that Python and Perl are both scripting languages, but there might be more to it.  I will have to come back to this topic after a few months with Python when I&#8217;ll be better equipped to make a more informed comparison.</p>
<h2> System Calls and Callbacks</h2>
<p>With that segue aside, it&#8217;s time to move into the meat of todays article.  I&#8217;d like to start by posting, of all things, a bit of C code that I&#8217;ve kept around to use every now and then when I need to walk through a directory structure.</p>
<pre>
<code>
void stat_file(const char* pathname)
{
    if(NULL == pathname)
        return;

    struct stat st;
    if(0 != stat(pathname, &amp;st))
    {
        printf("error opening %s: %s\n",pathname, strerror(errno));
    }
    printf("%d %s",st.st_size,pathname);
    return;
}

void callback_traverse(const char* dirname, void (*callback)(const char*), int traversal_type, int return_type, int level=0)
{
        DIR* dir = NULL;
        struct dirent* entry;
        char* path = (char*)malloc( (255*(level+1)) * sizeof(char) );
        strcpy(path,dirname);
        strcat(path,"/");

        callback(dirname);
        if(NULL != (dir = opendir(dirname)))
        {
                while( (entry = readdir(dir)) != NULL)
                {
                        if( (entry-&gt;d_name)[0]=='.')
                                continue;
                        strcat(path,entry-&gt;d_name);
                        callback_traverse(entry-&gt;d_name,callback,traversal_type,return_type,level+1);
                        strcpy(path,dirname);
                        strcat(path,"/");
                }
        }
        closedir(dir);
        free(path);
        path=NULL;
}
</code>
</pre>
<p>and now the equivalent Python code:</p>
<pre>
<code>
def stat_file(pathname):
    r = stat(pathname)
    print r.st_size,pathname
#def

def traverse_path(pathname, fun):
    for root, dirs, files in walk(pathname):
        for file in files:
            fun(file)
        #for
    #for
#traverse_path
</code>
</pre>
<p>One thing you can see immediately is that the Python code is quite a bit shorter.  The C code certainly has more error checking, a small bit of which may be useful in the python application as well, but by and large the python version is shorter.  That said, I have to say that I don&#8217;t necessarily find that the Python code was easier to write; certainly part of that is just my unfamiliarity with Python, but the algorithm is basically the same, except that Python is implementing parts of it under the hood.</p>
<p>Easier or not though, I do have to give credit to Python since the fact is that I was able to write the application.  My programming forte is mucking about at the systems level; I do certainly write applications level things from time to time, but as a systems developer, I think it&#8217;s nice that Python does at least have access to system calls.  That alone is enough to move python up a notch in my internal ranking of programming languages, thanks to the ease with which I was able to write the above application, I think I can now say that I would prefer to write Python code compared to Java (and the fact is that, while I don&#8217;t write a lot of Java these days, I&#8217;ve never particularly minded it).</p>
<p>Looking at the above code, the important technical bit is obviously the ability to pass a function as an argument to a function.  Python, with it&#8217;s at least half-hearted nod to functional programming, does at least gain one important win over C and C++ in this area; I don&#8217;t think that anyone in their right mind would argue against the fact that function pointer syntax in those languages is a bit much at times.</p>
<p>But, passing functions as arguments and working with systems calls are things I generally expect of any language, and it works well enough and without anything spectacular enough to merit droning on about.  There was, however, one thing that came up while figuring out how to write this code that I think is deserving of a bit of a rant.</p>
<h2>Pydoc</h2>
<p>I like man pages.  Some people use reference books or google when they are doing development (I use both on occasion) but more than anything else I like man pages for reference on all of the ins and outs of functions and structures that I&#8217;m using while doing development.  This, again, probably is a symptom of my systems programming roots, but pretty much every library and system call that I use in my day-to-day development has a corresponding and well written man page describing the return values, parameters, how exactly the function works, etc.  Using vim as my text editor, I have only to move the cursor over the function that I want to reference, and type &#8216;K&#8217; to get the man page up on the screen for my perusal.</p>
<p>Python does not use man pages.  There is certainly a man page for python, and plenty of available documentation, but most of the information is found through Python&#8217;s pydoc application.  pydoc works pretty much like man, supporting the main features that I use with man (forward and backward scrolling, and searching).  Vim is even smart enough to use Pydoc instead of man when it sees that I&#8217;m working with a python file.  The problem that I&#8217;ve run into with pydoc is, to be fair, as much of a problem with vim as with pydoc itself.  The problem is that, to search for a given function, you need to type the full &#8216;path&#8217;; so for instance to look up the &#8216;walk&#8217; function, one needs to run pydoc os.path.walk.  Another big problem is that pydoc os contains information about walk as well, but this information is different than the information in os.path.walk &#8211; and in both cases, simply typing &#8216;walk&#8217; and then &#8216;K&#8217; doesn&#8217;t open up the right pydoc page, meaning that I&#8217;m forced to manually type in !pydoc  in vim rather than just using &#8216;K&#8217;.</p>
<p>I understand that this eliminates the very real possiblity of two packages having functions with the same name that need documenting, but I&#8217;d much prefer that pydoc at least try to search for what I&#8217;m looking for, and prompt me to choose one if multiple results are found.</p>
<h2> Typing in Python </h2>
<p>In the last entry, a reader commented that they would like me to discuss my feelings on the auto typing that Python uses, compared to typing in other languages.  Since I&#8217;m still getting started on my journey to learning python, I&#8217;m not qualified to get too in depth on a discussion in this arena yet, but I thought I would at least address the issue at a high level and offer up my thoughts.</p>
<p>The first thing to realize is that python isn&#8217;t, strictly speaking, a dynamically typed language.  Under the hood, python resembles C++ and Java more strongly than, for instance, perl.  Python variables have an internal type, and in python you are prohibited from doing things like adding a number to a string, without calling some sort of conversation function at any rate.  Python also allows you to explicitly cast a type, allowing you to say, for instance, <code> foo = (int)some_function()</code>.</p>
<p>Fundamentally, I think that this is a good compromise, with a few potential potholes.  Having an internal type does mean that you will get errors on certain types of code that perl might happily parse, leading to a more subtly broken program.  Having an exception up right away avoids these problems.  Unfortunately, python doesn&#8217;t go quite far enough in my opinion.  While you can do something like <code> foo = (int)3.14</code> to get 3; you can&#8217;t cast between integer and character types (a side effect, I believe, of both pythons string object, as well as the way python handles unicode).</p>
<p>The other problem with implicit rather than explicit typing is that it hides what the programmer is thinking.  When you&#8217;re looking at a bit of C or C++ code, and you say &#8220;int some_value = some_function()&#8221; then the next programmer knows that (unless you are a horrible horrible programming) odds are you intend that to be a number.  In python, if you type &#8220;some_value = some_function()&#8221; then you have to either explicitly comment that (and we all know how much developers love to comment code) or rely on the next programming to go along and trace through some_function to see what it returns, so that they know what type of value &#8220;some_value&#8221; should be expected to have.</p>
<p>That said, implicit typing isn&#8217;t all bad, and I would say that as long as you choose variable names properly (or, shudder, use something like hungarian notation) you should be good.  As an interesting side node, C++0x is adding the &#8216;auto&#8217; keyword for automatically determining types, meaning that this will soon be one less advantage (or disadvantage depending on your perspective and circumstances) that Python has over C++.</p>
<h2> Closing Remarks </h2>
<p>Another few days with Python, and I have to say that some of my initial reservations are starting to go away.  There are certainly still things that I dislike about the language, but I&#8217;m starting to see that it has cases where it could indeed be useful.  I don&#8217;t anticipate that it will ever become my primary language choice, but I may be getting to the point where I could see myself not minding using here or there when it would be a good fit.  Over the next few days I&#8217;ll be looking at OOP in python.  I&#8217;ll be updating again soon so check back regularly, and if there are any topics you&#8217;d especially like me to cover, drop me an email or leave a comment and I&#8217;ll try to address it in the next post.</p>
<p>Thanks for reading; codeninja out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tuxtips.org/?feed=rss2&amp;p=14</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Journey to Python Part 1: First Steps</title>
		<link>http://www.tuxtips.org/?p=13</link>
		<comments>http://www.tuxtips.org/?p=13#comments</comments>
		<pubDate>Wed, 13 Aug 2008 00:39:09 +0000</pubDate>
		<dc:creator>codeninja</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.tuxtips.org/?p=13</guid>
		<description><![CDATA[After yesterdays rather long introduction into the whys and wherefores of my decision to learn python, today I&#8217;m going to begin to talk about my first steps into learning python.  In this post I&#8217;ll talk about how I fared getting up and running with python, what references I chose, and discuss my impressions after [...]]]></description>
			<content:encoded><![CDATA[<p>After yesterdays rather long introduction into the whys and wherefores of my decision to learn python, today I&#8217;m going to begin to talk about my first steps into learning python.  In this post I&#8217;ll talk about how I fared getting up and running with python, what references I chose, and discuss my impressions after writing my first program.<br />
<span id="more-13"></span></p>
<p>For someone who does not have experience with programming, getting started developing can be a daunting task.  Having the advantage of being a developer, and knowing several other languages, I started out today with a general idea of what I would need to get started and write my first application.  To get started I knew that I would need:</p>
<ul>
<li>the Python interpreter, to run the applications
<li>an editor, to write applications
<li>documentation, to know <i>how</i> to write the programs
<li>a program to write
</ul>
<h2>Getting the environment up and running</h2>
<p>Since I have been running Python applications before starting development, I knew that I already had the basic environment that I would need.  For those of you following along at home, running linux you will probably find that you already have linux installed, or can easily find the packages on your installation disks or in your distribution repositories (<i>Ubuntu and Debian users install the python2.5 and python2.5-doc packages from your repositories</i>).  OS X users should already have python installed, and Windows users can grab python from <a href="http://www.python.org">python.org</a></p>
<h2>Setting up a development environment</h2>
<p>Once again, I was able to benefit from previous experience.  Since I prefer to do my C, C++ and Perl development from the command line with vim, I was ready to go with my editor of choice.  Vim already had support for python syntax, and with syntax highlighting and auto-indent already enabled, I had nothing to do to get started.  If you haven&#8217;t taken the time to set up a development environment already, you can grab my <a href="http://tuxtips.org/vimrc">vimrc</a> file, and save it to <i>~/.vimrc</i> to get a head start (<i>ubuntu users: if you haven&#8217;t done so already, you may want to install a more full featured vim (e.g. vim-gnome or vim-full) since the default vim installed on ubuntu is rather limited</i>)</p>
<h2>Documentation</h2>
<p>Although man pages are a useful reference, they aren&#8217;t the best way to get started learning a new programming language.  To get started, I decided to check out the <a href="http://docs.python.org/tut/tut.html">Official Tutorial</a>.  The tutorial itself seems to be pretty good.  I&#8217;ve made it through section 4 so far, and it seems to be a good reference.  Of course, I also find having a dead-tree reference to be useful, not only for learning but for referring back to later.  To supplement the official tutorial, I decided to pick up O&#8217;Reilly&#8217;s <a href="http://oreilly.com/catalog/9780596002817/">Learning Python</a>  since I&#8217;ve always been a fan of the Learning $foo series from O&#8217;Reilly.  I personally prefer <i>Learning Python</i> to the official tutorial, since it seems to get into the details more quickly, plus it has exercises that will serve useful later when I run out of ideas for sample programs to write.</p>
<h2>Getting Stuff Done</h2>
<p>With an editor and interpreter ready to go, and documentation on hand, I set to work writing my first Python application.  I wanted to get a basic feel for the language, and be able to start with something extremely simple.  To start with, I knew that I wanted to be able to demonstrate:</p>
<ul>
<li>Putting text on the screen</li>
<li>Using conrol structures (loops, branching)</li>
<li>Create a function</li>
<li>Do some math</li>
<li>Use a library</li>
</ul>
<p>I decided to start with a simple program that would calculate some interesting facts about a list of numbers, and print them to the screen.  At this point I am more concerned with simply being able to use the language than being idiomatic about it.  Below is my first ever Python application:</p>
<p><code></p>
<pre>
#!/usr/bin/python
import math

def fibnum(n):
    if n &lt;= 1:
        return 1
    else:
        return fibnum(n-1) + fibnum(n-2)

def factorial(n):
    if n &lt;= 1:
        return 1
    else:
        return n * factorial(n-1)

def isprime(n):
    if n &lt; 2:
        return False
    for x in range(2,(int)(math.sqrt(n))+1):
        if ((n%x) == 0):
            return False
    return True

for x in range(0,10):
    print "%(x)dth fibonacci number is %(fib)d"%{"x":x,"fib":fibnum(x)}
    print '%(x)d! =%(fact)d'%{'x':x,'fact':factorial(x)}
    print x,"is",
    if not isprime(x):
        print "not",
    print "prime"
</pre>
<p></code></p>
<p>and here is the output:</p>
<pre>
0! =1
0 is not prime
1th fibonacci number is 1
1! =1
1 is not prime
2th fibonacci number is 2
2! =2
2 is prime
3th fibonacci number is 3
3! =6
3 is prime
4th fibonacci number is 5
4! =24
4 is not prime
5th fibonacci number is 8
5! =120
5 is prime
6th fibonacci number is 13
6! =720
6 is not prime
7th fibonacci number is 21
7! =5040
7 is prime
8th fibonacci number is 34
8! =40320
8 is not prime
9th fibonacci number is 55
9! =362880
9 is not prime
</pre>
<p>As you can see, the program simply iterates through the numbers 0-9 and calculates the nth fibonacci number, n!, and determines if n is prime or not, and displays this information to the screen.</p>
<p>With my first Python program actually written and running, it&#8217;s time to go over my thoughts on day 1.  To start, I found that the syntax wasn&#8217;t that bad, but at the same time, I&#8217;m not yet convinced that it&#8217;s in any way superior to C, C++, or even perl.  Significant whitespaces weren&#8217;t as big of a deal as I had expected, but I found the lack of a closing curly brace &#8216;}&#8217; to end a function made it hard to visually scan and see where one block of code ends and another begins.  Since we already have to use a colon &#8216;:&#8217; to define the start of a block, it just seems like sheer pigheadedness to not to ahead and just end a block of code with some identifiable token.  The print statement also seems to be different-for-the-sake-of-being-different.  The print formatting is reminiscent of C&#8217;s printf function, but the choice of &#8220;format&#8221;%{dictionary} instead of just &#8220;format&#8221;,&#8230; seems nasty to me.  I will have to see if this choice imbues any greater flexibility later that makes up for it&#8217;s quirkiness.  The for in loop syntax is nice, and very similar to perl&#8217;s foreach and nearly identical to php&#8217;s for in loops, and I&#8217;m glad to see at least one language feature so far that seems reasonable and intuitive to me.  Finally, to pick on last nit, making &#8216;True&#8217; and &#8216;False&#8217; start with capital letters is irritating; I have no idea how in the world capitalizing them is supposed to make code more intuitive or readable, so once again I&#8217;m left with the thought that for all of it&#8217;s talk about doing things better, python often does things different just for the sake of it.</p>
<p>Final thought for today: not as painful as it could have been, but certainly less of a joy that programming in C or Perl for me so far.  There are quite a few &#8216;features&#8217; that I&#8217;m on the fence about right now- I&#8217;ll have to see if they turn out to be more powerful once I&#8217;ve gotten some more Python experience under my belt.  I hate having to capitalize &#8220;True&#8221; and &#8220;False&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tuxtips.org/?feed=rss2&amp;p=13</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Journey to Python: Introduction</title>
		<link>http://www.tuxtips.org/?p=12</link>
		<comments>http://www.tuxtips.org/?p=12#comments</comments>
		<pubDate>Tue, 12 Aug 2008 04:00:58 +0000</pubDate>
		<dc:creator>codeninja</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.tuxtips.org/?p=12</guid>
		<description><![CDATA[There is something that I have to admit, even though it may cost me a few geek points.  I&#8217;m not fashionable.  I&#8217;m not quite the old codger who things things were fine with punchcards and this internet thing is just a fad, I certainly enjoy using the latest version of $whizbang_app, and I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>There is something that I have to admit, even though it may cost me a few geek points.  I&#8217;m not fashionable.  I&#8217;m not quite the old codger who things things were fine with punchcards and this internet thing is just a fad, I certainly enjoy using the latest version of $whizbang_app, and I&#8217;m happy to upgrade my hardware with acme&#8217;s Greatest-Thing-Ever(tm).  I was using Linux on the desktop when most people were trying to decide if they should upgrade to Windows 98, and I was running Compiz when it was just a couple of tarballs and a neat video from Novell.  In certain areas however, I am far more conservative.<br />
<span id="more-12"></span></p>
<p>As a software developer, it&#8217;s important for me to stay on the leading edge of software development trends.  Fail to keep up and you could just find yourself stuck maintaining legacy code in a dreary job for the rest of your life.  The problem is that software development is particularly prone to Best-Thing-Ever syndrome.  Programmers are often accused of having ADD, and there are few places this accusation is so aptly demonstrated than in the seemingly weekly changes in &#8220;the one true language&#8221;, &#8220;the one true paradigm&#8221;, &#8220;the one true pattern&#8221;.</p>
<p>I&#8217;m not talking here about enterprise programming, although enterprise development certainly has it&#8217;s share of bandwagons.  What I&#8217;m really talking about here is programmer culture (or what I would have called hacker culture had the term not been bastardized). I&#8217;m not trying to say that this is a bad thing, it&#8217;s part of what makes programming culture what it is, but it&#8217;s something to be aware of.</p>
<p>A lot of these &#8220;greatest things ever&#8221; are good ideas, often temporarily over-hyped, but they serve a solid purpose and are useful in their context.  Even the ones that aren&#8217;t useful are often at least fun to play around with.  Times change to quickly, however, and nobody can be an expert in (or even familiar with) every &#8220;greatest thing ever.&#8221;  It&#8217;s easy to miss things because of lack of time, and sometimes &#8220;the greatest thing ever&#8221; just doesn&#8217;t seem so great, and it gets ignored.</p>
<p>Python, for me, has falling into both of the latter two categories.  I originally looked at Python back in 2000, because I was interested in trying to fix a bug in Redhat&#8217;s Anaconda installer.  Since Python hadn&#8217;t really gained the large following that it currently has, combined with the fact that I was a fairly inexperienced developer with limited internet access at the time, I never really got very far in my ambition, and quickly moved on.  Python continued to grow however.</p>
<p>I started hearing a lot about python in 2006 or so, and by 2007 it had really started to reach a critical mass of popularity.  Hearing all of the good things about Python, and remembering back when I had tried to learn it several years ago, I decided to look back in on it early in 2007.  Perhaps it was too soon since I&#8217;d had to take a COBOL class and the significant whitespace thing put me off, or maybe the stars were just aligned in a certain way, but I was not really impressed with python.</p>
<p>The syntax seemed ugly to me, the &#8220;there&#8217;s only one way to do it&#8221; philosophy was at odds with my personal philosophy of &#8220;give the developer as much power and flexibility as possible&#8221;, and the fact that every introduction to python I read basically told me that I was a bad developer, and my favorite languages (C++ and perl) sucked, and I should be thankful for having python to rescue me &#8211; it all added up to put me pretty dead set against python.  In fact, all of those things <i><b>still</b></i> keep my bias against python; but in the end we can&#8217;t be a slave to our bias.</p>
<p>Over the last year, I&#8217;ve noticed that a lot of the applications that I&#8217;m using are written in python.  Music players, Desktop widgets, version control systems, and even my favorite websites are all being re-written or replaced by versions written in python.  For the most part, I&#8217;ve never had a problem with this.  If a program works well, then who cares what it&#8217;s written in; and I know that a lot of people never shared my own personal bias against python.  That said, the transition to more applications being written in python did have an effect; subtle at first it grew more noticeable as time went on, and eventually culminated in my decision to finally sit down and get comfortable with python.</p>
<p>As a Linux C and C++ developer, I always had a fairly distinct advantage over a lot of other people when it came to the Linux desktop.  C and C++ were the dominant languages for a long time for even desktop applications under Linux.  I had the advantage of speaking the lingua franca.  Not only did free software give me the right to have and modify the code, but the fact was most code was written in my preferred languages (C, C++, perl).  Using the rights afforded to my by the GPL and other free software licenses was a practical and easy thing for me to do.  But every python application on my system is an application written in a foreign language; by not knowing python I was leaving myself in a position where I was unable to exercise my freedom to alter the free software on my computer.</p>
<p>So, all of that to say this:  I&#8217;ve decided to make my peace with python.  After I&#8217;ve used it for a while I may learn to like it, or I may always have a lingering hatred for the language for either technical reasons, or purely because I can&#8217;t get over my own issues, but at least, love it or hate it, I&#8217;ll be able to use it as another tool in my repertoire.  And, in the spirit of keeping myself on track and honest about it, I&#8217;ve decided to document the whole process right here on tuxtips.org.  I&#8217;ll be posting every couple of days with my updates on what I&#8217;ve learned, what I&#8217;m liking, and what I&#8217;m not liking.  A live feed of the thoughts, trials, and tribulations of a systems programmer with a bias against python taking the dive to learn what it&#8217;s really about.</p>
<p>Stay tuned for part 1 tomorrow, where I&#8217;ll discuss the books and documentation I&#8217;m using to learn, my development environment, and my learning plan and goals.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tuxtips.org/?feed=rss2&amp;p=12</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Understanding /proc</title>
		<link>http://www.tuxtips.org/?p=11</link>
		<comments>http://www.tuxtips.org/?p=11#comments</comments>
		<pubDate>Tue, 03 Jun 2008 05:35:33 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[linux sysadmin kernel programming proc]]></category>

		<guid isPermaLink="false">http://www.tuxtips.org/?p=11</guid>
		<description><![CDATA[/proc is often considered one of the most mysterious parts of the linux file system.  For those comming from the windows world especially, but also those who have been using Linux for years, proc seems an at times incomprehensible web of mysterious files and directories.
Understanding the mysteries of /proc can greatly aid in administrering and [...]]]></description>
			<content:encoded><![CDATA[<p>/proc is often considered one of the most mysterious parts of the linux file system.  For those comming from the windows world especially, but also those who have been using Linux for years, proc seems an at times incomprehensible web of mysterious files and directories.</p>
<p>Understanding the mysteries of /proc can greatly aid in administrering and programming on linux systems, because proc is itself a key into the depths of the system.  In some ways, proc can be thought of as similar to the windows registry; it contains specific files that contain information about the system, and control how the system operates.</p>
<p><span id="more-11"></span></p>
<p>There are two main ways that proc can be used: to monitor and keep track of processes, and to monitor and tune the kernel.</p>
<p>On the process side, proc has subdirectories for each currently running process.  The numeric directory entires in proc are PIDs representing the currently running processes.  Inside the directory for each PID are a number of useful files that can be used both from the command line to get information about a process, and, especially, from within the application in order to get useful information about itself.</p>
<p>Of particular note are:</p>
<ul>
<li>cmdline: this contains the command used to launch the application</li>
<li>cwd: a simlink to the applications current working directory</li>
<li>exe: a simlink to the application running</li>
<li>status: contains useful information; especially useful for seeing memory usage</li>
</ul>
<p>Outside of using proc to gain information regarding processes, proc also contains useful system information.  Of particular note are:</p>
<ul>
<li>cmdline: contains the kernel boot parameters, useful for custom init scripts</li>
<li>cpuinfo: contains information about the processors or cores in the system</li>
<li>loadavg: contains the system load average</li>
<li>self: a simlink to the PID directory for the current process</li>
</ul>
<p>Learning to effectively use proc can greatly ehnance the ability and ease with which you can tune your system, as well as allowing your applications to effectively manage and monitor themselves and other processes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tuxtips.org/?feed=rss2&amp;p=11</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ひらがな (Hiragana), カタカナ (Katakana), and 漢字 (Kanji) Input in Gnome</title>
		<link>http://www.tuxtips.org/?p=9</link>
		<comments>http://www.tuxtips.org/?p=9#comments</comments>
		<pubDate>Wed, 19 Mar 2008 01:37:41 +0000</pubDate>
		<dc:creator>codeninja</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[gnome]]></category>
		<category><![CDATA[input]]></category>
		<category><![CDATA[japanese]]></category>

		<guid isPermaLink="false">http://www.tuxtips.org/?p=9</guid>
		<description><![CDATA[A few days ago I decided to start learning Japanese.  I expected to have a difficult path ahead of me, as Japanese is a notoriously difficult language for westerners to learn.  After running up to my local bookstore, and picking up several books and CDs on the Japanese language, and getting the Adobe [...]]]></description>
			<content:encoded><![CDATA[<p>A few days ago I decided to start learning Japanese.  I expected to have a difficult path ahead of me, as Japanese is a notoriously difficult language for westerners to learn.  After running up to my local bookstore, and picking up several books and CDs on the Japanese language, and getting the Adobe Shockwave plugin installed using <a href="http://codeweavers.com">Crossover Office</a> (A great version of wine, I definitely recommend it if you find the vanilla wine to be too cumbersome); and making myself slightly poorer buy getting a subscription to the online version of <a href="http://www.rosettastone.com">Rosetta Stone</a> I found myself facing a difficulty that I hadn&#8217;t originally expected.  My English version of Slackware with Dropline Gnome and a US keyboard layout allowed me no easy way to insert Japanese script into documents.  This meant that I would have difficult learning to read and write Japanese, as well as practicing Japanese by talking with my Japanese speaking friends online.<br />
Knowing that there had to be a solution to this problem, I set out on the internet to find out.  Unfortunately, the general (and reasonable) assumption is that if you want to be able to input Japanese characters, you probably read Japanese.  For someone just learning the language, I found a lot of the documentation rather incomprehensable.  With some effort I figured out how to get everything working, and have here a guide that should help others who want to enable Japanese character input.<br />
<span id="more-9"></span></p>
<p>
To start with, you will need 3 packages.  I&#8217;ve provided a mirror of the packages here since I had some trouble tracking them down.</p>
<ul>
<li><a href="http://tuxtips.org/software/Canna37p3.tar.bz2">Canna Server</a> is a daemon that converts english characters into Kana
<li><a href="http://tuxtips.org/software/im-ja-1.5.tar.gz">Im-Ja</a> A utility to allow you to type in romanji and get the appropriate characters
<li><a href="http://tuxtips.org/software/scim-1.4.7.tar.gz">scim</a> A utility used by im-ja to talk to the canna server
</ul>
<p>If you don&#8217;t have it, you will also need the xmkmf utility; this was already available on slackware, and is probably available for your distribution as well.<br />
Start by installing the canna server, scim, and im-ja in that order.  Building the packages is fairly simple, just extract them, and run:</p>
<pre>
xmkmf
make Makefiles
make
make install
</pre>
<p>
After the packages have been installed, you need to edit your gtk.immodules command:</p>
<pre>
sudo vim /etc/gtk-2.0/gtk.immodules
</pre>
<p>and append the following lines:</p>
<pre>
"/usr/lib/gtk-2.0/2.10.0/immodules/im-ja.so"
"im-ja" "Japanese" "gtk+" "/usr/share/locale" "ja"
</pre>
<p><i>Note: replace 2.10.0 with your version of Gtk+</i><br />
Next, run the <b>im-ja-conf</b> utility, and set your shortcut keys.  In my configuration, I have:</p>
<ul>
<li>Switch to next input mode &#8211; CTRL space
<li>Set direct input mode &#8211; MOD4 (windows key) n
<li>Toggle hiragana/direct mode &#8211; MOD4 h
<li>Toggle full/half-width katakana mode MOD4 k
</ul>
<p>Log out of Gnome and back in so that all of your applications will have the appropriate libraries available.<br />
Once you are back in Gnome, if you want to enter some japanese characters, in a text box, right click and choose <b>Input Mode -&gt; Japanese</b>  Start typing in romanji and the characters will appear in a small floating text box.  Use space to select characters or finish entering a word.<br />
With these tools in hand, you can easily begin learning Japanese, or set up a machine that is usable for someone already familiar with the language.  If you are learning Japanese, you might also find the <a href="http://clay.ll.pl/kanatest/">Kanatest</a> program useful.  It will allow you to test and practice your knowledge of japanese characters!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tuxtips.org/?feed=rss2&amp;p=9</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extending Nautilus With Scripts (Part 1)</title>
		<link>http://www.tuxtips.org/?p=8</link>
		<comments>http://www.tuxtips.org/?p=8#comments</comments>
		<pubDate>Sun, 02 Mar 2008 02:31:32 +0000</pubDate>
		<dc:creator>codeninja</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[gnome]]></category>
		<category><![CDATA[nautilus]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://www.tuxtips.org/?p=8</guid>
		<description><![CDATA[One of the great benefits of Linux is it&#8217;s extensibility.  For Gnome users, one of the great ways that you can easy expand and customize your desktop is with Nautilus scripts.  In this article I discuss using Nautilus scripts to enhance your Gnome experience, as well as providing a couple of starter scripts.

A [...]]]></description>
			<content:encoded><![CDATA[<p>One of the great benefits of Linux is it&#8217;s extensibility.  For Gnome users, one of the great ways that you can easy expand and customize your desktop is with Nautilus scripts.  In this article I discuss using Nautilus scripts to enhance your Gnome experience, as well as providing a couple of starter scripts.<br />
<span id="more-8"></span><br />
A Nautilus script can be any executable file.  When these scripts are put in a special location, or else referred to in a .desktop file, nautilus will execute them with special environment variables set, and with special command line arguments.  For the first part of this two-part article, I will discuss nautilus file browser scripts, which you can access from the &#8220;Scripts&#8221; menu in the context menu of the Nautilus file browser.  This menu will list all of the executable files that are in the
<pre> ~/.gnome2/nautilus-scripts </pre>
<p> directory.</p>
<p />
When dealing with executable files, the paths for the selected files are passed in as command line arguments to the application.  So, for C or C++ applications, you would parse the selected files by looping through the argv list.  For shell scripts, Nautilus sets a number of useful environment variables that let you determine what files are selected, and what directory you are in.  The environment variables set by Nautilus are:</p>
<ul>
<li>
<pre> NAUTILUS_SCRIPT_SELECTED_FILE_PATHS </pre>
<p> &middot; This variable lists the paths of the currently selected files, separated by newlines.  This only works on local filesystems.</p>
<li>
<pre> NAUTILUS_SCRIPT_SELECTED_URIS </pre>
<p> &middot; This variable contains the URIs (file://file) of the selected files, separated by newlines.  This works on both local and remote filesystems.</p>
<li>
<pre> NAUTILUS_SCRIPT_CURRENT_URI </pre>
<p> &middot; This contains the URI of the current directory.  This works for both local and remote filesystems.</p>
<li>
<pre> NAUTILUS_SCRIPT_WINDOW_GEOMETRY </pre>
<p> &middot; This provides you with the window location and geometry of the browser window.
</ul>
<p>
If you choose &#8220;Open Scripts Folder&#8221; from the scripts submenu, you will also get a pop-up window giving you this information.</p>
<p />
To give you an example of how to use Nautilus scripts, I&#8217;ve provided a few useful scripts that you can use and modify yourself to get started with Nautilus scripting.</p>
<p><b>Open Terminal Here</b><br />
This script opens a gnome-terminal in the current directory, using the default profile.</p>
<pre>
#!/bin/bash
gnome-terminal --working-directory=`echo $NAUTILUS_SCRIPT_CURRENT_URI | sed -e "s/file:\/\///"`
</pre>
<p />
<b>Remove Spaces</b><br />
This script replaces spaces with underscores for all files in the current directory.</p>
<pre>
#!/usr/bin/perl
foreach(split(/\n/,`ls`))
{
	($of=$_)=~s/\s/_/g;
	`mv "$_" $of`;
}
</pre>
<p />
<b>ogg2mp3</b><br />
A script to convert all of the .ogg files in a directory into mp3&#8217;s</p>
<pre>#!/bin/bash
oggdec $1.ogg
lame --preset 192 -ms -h $1.wav -o $1.mp3
rm $1.wav
</pre>
<p />
<b>Un-Subdirectory</b><br />
This script moves all the files in all subdirectories into the current directory.  This is useful for creating playlists and slideshows, or for re-organizing files.</p>
<pre>#!/usr/bin/perl

chomp($top = `pwd`);

mvhere(".");

sub mvhere
{
	$dir = shift;
	chdir($dir);
	my $cwd = $top."/".$dir;
	for $f (`ls`)
	{
		chomp($f);
		if(-d $f)
		{
			mvhere($f);
		}
		elsif(-f $f)
		{
			`mv $f $top/`;
		}
	}
	chdir("..");
}
</pre>
<p />
Well, there you have it.  Now you can continue on customizing your own environment to automate tedious or common tasks.  In the next part of this article we will discuss creating drag-and-drop scripted icons on your desktop, allowing you to script events based on dragging icons onto a special desktop scripted icon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tuxtips.org/?feed=rss2&amp;p=8</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating a File Tree with Gtk+</title>
		<link>http://www.tuxtips.org/?p=7</link>
		<comments>http://www.tuxtips.org/?p=7#comments</comments>
		<pubDate>Wed, 20 Feb 2008 04:06:52 +0000</pubDate>
		<dc:creator>codeninja</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.tuxtips.org/?p=7</guid>
		<description><![CDATA[I thought that today, rather than going for an in-depth tutorial, I would post a useful snippet of code for anyone out there doing GUI development with GTK+.  Although Gtk+ is a nice toolkit, one thing that I found that it was lacking was a nice widget to automatically display directories.  I had [...]]]></description>
			<content:encoded><![CDATA[<p>I thought that today, rather than going for an in-depth tutorial, I would post a useful snippet of code for anyone out there doing GUI development with GTK+.  Although Gtk+ is a nice toolkit, one thing that I found that it was lacking was a nice widget to automatically display directories.  I had hoped that since it had such a nice file open dialog, there might be something out there, but alas I was unable to find anything.  So, I present here a useful function to automatically populate a GtkTreeView with a directory structure.<br />
<span id="more-7"></span></p>
<hr />
<font color="#2e8b57"><b>void</b></font>&nbsp;fill_tree(<font color="#2e8b57"><b>char</b></font>* dirname, <font color="#2e8b57"><b>char</b></font>* shortname, GtkTreeStore* store, GtkTreeIter* parent_iter, <font color="#2e8b57"><b>int</b></font>&nbsp;level)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>DIR</b></font>* dir = <font color="#ff00ff">NULL</font>;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//defined in dirent.h</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>struct</b></font>&nbsp;dirent* entry;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//allocate a string with 255 characters per directory name, plus 1 character for the / between directories.</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>char</b></font>* path = (<font color="#2e8b57"><b>char</b></font>*)malloc( ((<font color="#ff00ff">255</font>*(level+<font color="#ff00ff">1</font>))+level+<font color="#ff00ff">1</font>) * <font color="#a52a2a"><b>sizeof</b></font>(<font color="#2e8b57"><b>char</b></font>) );</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//this will become the parent node for subsequent calls</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//and gets placed under the parent node that was sent to us</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GtkTreeIter my_iter;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcpy(path,dirname);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcat(path,<font color="#ff00ff">&quot;/&quot;</font>);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a"><b>if</b></font>(<font color="#ff00ff">NULL</font>&nbsp;!= (dir = opendir(dirname)))<font color="#0000ff">//make sure we can open the directory</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//create a node on the tree for the directory</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gtk_tree_store_append(store,&amp;my_iter,parent_iter);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//add the current directory to the list</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gtk_tree_store_set(store,&amp;my_iter,COL_NAME,shortname,-<font color="#ff00ff">1</font>);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//start to read the subdirectories</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a"><b>while</b></font>( (entry = readdir(dir)) != <font color="#ff00ff">NULL</font>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//skip hidden files, . and ..</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a"><b>if</b></font>( (entry-&gt;d_name)[<font color="#ff00ff">0</font>]==<font color="#ff00ff">&#8216;.&#8217;</font>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a"><b>continue</b></font>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//create the full path to the subdirecotry</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcat(path,entry-&gt;d_name);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//recursively call fill with this subdirectory</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fill_tree(path,entry-&gt;d_name,store,&amp;my_iter,level+<font color="#ff00ff">1</font>);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//reset the path to the path of this directory</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcpy(path,dirname);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcat(path,<font color="#ff00ff">&quot;/&quot;</font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//close the file handle and free memory</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;closedir(dir);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(path);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;path=<font color="#ff00ff">NULL</font>;<br />
}<br />
</font></p>
<hr />
Using the function is pretty simple.  Just copy and paste into your application, with the path for the top of the directory structure you want to display, and a name for it.  Pass in a pointer to a GtkTreeStore you&#8217;ve allocated, and NULL and 0 for the parent_iter and level (unless you want to display the tree under some heading).  Here is an example:</p>
<pre>
fill_tree("/home/tuxtips","Home Directory",my_tree_store,NULL,0);
</pre>
<p>
If you are loading a large directory structure (for example, /) you might consider spawning this off into it&#8217;s own thread, as it can take a bit of time.  For something a bit more dynamic, consider removing the recursive functionality, and calling the function in response to a user clicking on an entry.  Also note that, for simplicity, I&#8217;ve used 255 as the maximum directory entry size, but this is a variable set in dirent.h and varies from system to system, so be sure to look that up!
<p>
Until Next Time, Happy Hacking.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tuxtips.org/?feed=rss2&amp;p=7</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apologies For Funky Formatting</title>
		<link>http://www.tuxtips.org/?p=6</link>
		<comments>http://www.tuxtips.org/?p=6#comments</comments>
		<pubDate>Tue, 29 Jan 2008 06:38:56 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Tuxtips]]></category>

		<guid isPermaLink="false">http://www.tuxtips.org/?p=6</guid>
		<description><![CDATA[Hey everyone,
I just wanted to write up a quick post to apologize for the funky formatting of code in the last post.  I&#8217;m currently trying to figure out the best way to get code to look right inside of wordpress, without the WYSWYG editor fubaring it.  As I work out the best way to format [...]]]></description>
			<content:encoded><![CDATA[<p>Hey everyone,</p>
<p>I just wanted to write up a quick post to apologize for the funky formatting of code in the last post.  I&#8217;m currently trying to figure out the best way to get code to look right inside of wordpress, without the WYSWYG editor fubaring it.  As I work out the best way to format code I&#8217;ll be going back to fix older posts, and I hope that you&#8217;ll stick with us through this refinement stage of the site.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tuxtips.org/?feed=rss2&amp;p=6</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pointer-to-Member functions &amp; pthreads in C++</title>
		<link>http://www.tuxtips.org/?p=5</link>
		<comments>http://www.tuxtips.org/?p=5#comments</comments>
		<pubDate>Tue, 29 Jan 2008 05:37:16 +0000</pubDate>
		<dc:creator>codeninja</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.tuxtips.org/?p=5</guid>
		<description><![CDATA[A common development problem, and one that is becoming even more important as processors gain more cores, and computers themselves gain more processors, is the issue of concurrency.  Dealing with concurrency, that is to say multithreaded programming, is vitally important for obtaining top level performance on modern systems.  Even in cases where performance [...]]]></description>
			<content:encoded><![CDATA[<p>A common development problem, and one that is becoming even more important as processors gain more cores, and computers themselves gain more processors, is the issue of concurrency.  Dealing with concurrency, that is to say multithreaded programming, is vitally important for obtaining top level performance on modern systems.  Even in cases where performance isn&#8217;t critical, multithreaded programming (especially for GUIs) can vastly improve the user experience of an application.  In this part 1 of a series on concurrent programming with C++, I examine what makes using pthreads with C++ difficult at times, and suggest two methods for easily integrating pthreads with an Object-Oriented C++ application, along with an in-depth look at pointer-to-member function syntax and in the light of this practical application.</p>
<p><span id="more-5"></span><br />
Writing multithreaded applications is hard.  Luckily it&#8217;s the same sort of hard that applies programming in general, which is to say that the bulk of the difficulty comes from learning how to think about problems correctly in order to know when and how to apply multithreading.  It&#8217;s beyond the scope of this particular article to go into the design and architectural aspectects of multithreading an application,  but the difficulty of mixing threading with C++ extends beyond the conceptual aspects and into the meat of the development.</p>
<p>If you&#8217;ve come from a background of developing threaded applications in Java, or perhaps one of the more esoteric concurrent programming languages like Erlang, or to a lesser extent, from a pure C background, you might wonder why threading in C++ is so difficult.  To start with, let&#8217;s look at a bit of sample code:</p>
<pre>
#include
#include
using namespace std;

class example
{
	public:
		void say_something(char* something);
};

void example::say_something(char* something)
{
	cout&lt;&lt;something;
}

int main(int argc, char* argv[])
{
	example my_example;
	pthread_t my_thread;
	char message[] = {"hello world"};
	pthread_create(&amp;my_thread,NULL,&amp;my_example.something,s);//BROKEN!
	return 0;
}</pre>
<p>If you were familiar with languages like Java or C, you might wonder why this wouldn&#8217;t work.  To a C++ developer who has been dealing with the problem of getting C++ code to play nicely with threads, it&#8217;s an example of the difficulty of multithreading C++ applications.  There are a few different problems with this code.  Although some would say that it&#8217;s a syntax error, writing code like this, although not syntactically correct, is more of a symptom of misunderstanding the fundamental way that pthreads work, as well as difficulty that comes with mixing C libraries into C++ applications.</p>
<p>Often times examining the code more closely can help one to arrive at a solution, so let&#8217;s look at what the code is trying to do, and what might be the root cause of the failure.  Fundamentally, what we have is a class, with a member function called <em>say_something</em> which takes a <strong>char*</strong> as an argument, and prints that <strong>char* </strong>to the screen.  We want to run this function in it&#8217;s own thread, and then exit.  Now that we know what we want to do, let&#8217;s look at why this particular implementation will not work.  The compiler will generally give a single error and give up, but there are in fact a few different layers of errors that need to be addressed.  Most of these errors come from the definition of the pthread_create function, so to start with, let&#8217;s take a look at the prototype for the function.</p>
<pre>
int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start_function)(void*), void* args);</pre>
<p>The pthread_create function takes an address of a pthread_t, attributes (which are generally NULL), a pointer to a function that returns a void pointer, and takes as it&#8217;s argument a single void pointer, and a void pointer to the argument to the function.  So, of course, even were it not a class member, our say_something function, which returns void and takes a cstring would not have worked.  The real problem is that pthread_create expects a pointer to a function, but we are trying to pass it a pointer to a <strong>member</strong> function.</p>
<p>If the problem that this poses is immediately apparent to you, feel free to skip down to the end of this paragraph and peruse the code below, but if you don&#8217;t immediately understand why this is a problem read on, it is one of the cruxes of understanding the hows and whys of multithreaded development in C++.  Essentially, the issue comes down to whether the function has access to an implicit <strong>this</strong> pointer.  Global functions, and static member functions are not associated with any particular object.  You can, therefore, easily take the address of them, make pointers to them, and use them as callbacks.  Class member functions, on the other hand, need a little bit of extra information; they need a <strong>this </strong>to associate themselves with.  We can&#8217;t take the address of <em>my_example.something</em> because we lose the information related to the <strong>this</strong> pointer that the member function is associate with.  The following code snippet may help to illustrate the point of the necessity of a <strong>this </strong>pointer.</p>
<pre>
#include
#include
using namespace std;

class example
{
	public:
	string s;
	void say_hi()
	{
		cout&lt;&lt;"hello "&lt;*foo)();
	}
};

int main()
{
	example foo;
	example bar;
	foo.s = "world";
	bar.s = "there";
	foo.get_hi();
	bar.get_hi();
	void ((example::*f)()) =  bar.func();
	(foo.*f)();
	return 0;
}</pre>
<p>Compiling and running this application gives the following illuminating output:</p>
<blockquote><p> <strong>hello world</strong><br />
<strong>hello there</strong><br />
<strong>hello world</strong></p></blockquote>
<p>As you can see, although we took a function pointer from <em>bar</em> which had it&#8217;s string set to &#8220;there&#8221;, the output still shows foo&#8217;s string of &#8220;world&#8221;.  By calling <em>foo.f</em> we are telling <em>f </em>to use <em>foo</em> as it&#8217;s <strong>this</strong> pointer.  If it all sounds quite confusing and way too much trouble to bother with, well that&#8217;s because it usually is.  You don&#8217;t often see code like the above snippet precisely because it&#8217;s difficult to read, and doesn&#8217;t buy you much in practice (There are a few cases where this is incredibly handy, and if you run into one of those situations you will now recognized it and be prepared).  The reason for this was to illustrate why things we think should work when it comes to mulithreading with C++ don&#8217;t work.</p>
<p>So, you might think, that was a long winded explanation about why you can&#8217;t do something.  The astute reader however will realize that by going into detail about why things don&#8217;t work, I have layed out the pieces to one of the most common solutions to making them work.  As you may recall above, I pointed out that the limitation of requiring a valid <strong>this</strong> pointer applies only to <strong>non-static </strong>member functions<strong>.</strong>  We&#8217;ve also seen that we can call a pointer-to-member-function  if we explicitly provide a <strong>this</strong> pointer by using the <strong>-&gt; </strong>or <strong>. </strong>operators.  This opens up the groundwork for two solutions, one of which is easy to follow and implement, the other quite powerful.</p>
<p>For the first case, let us assume that we have a standard path of execution that a class will take, and that we simply want to run this path in it&#8217;s own thread.  In this case we can implement a solution very similar to implementing the <strong>Runnable</strong> interface in Java.  By creating a static class member function that takes a pointer to an object, we can simple use our pthread_create on this static function, and have the function call the appropriate entrance function of the data member it gets as it&#8217;s argument.  Look at the code below to illustrate this point:</p>
<pre>
#include
#include
#include
using namespace std
class example
{
	public:
		string s;
		void say_hi()
		{
			cout&lt;&lt;"hello "get_hi();
			return NULL;
		}
};

int main()
{
	pthread_t launch_thread;
	example foo;
	foo.s = "world";
	pthread_create(&amp;launch_thread, NULL, &amp;example::run, static_cast(&amp;foo));
	pthread_join(launch_thread,NULL);//added so we can see the output before we exit
	return 0;
}</pre>
<p>In this example, we have added a static function.  Since we can take the address of a static member function and treat it like a normal global function, we can easily pass this function into our pthread_create.  This lets us treat each instance of the class as a single threadable unit.  We can spawn off a thread to begin execution, and then let our class do it&#8217;s thing.  This simple approach can solve many issues that might crop up in implementing concurrency in a C++ application.  There are drawbacks however.</p>
<p>The previous approach limits in many ways.  First of all, we are limiting ourselves to a single entry point into the class.  If we want to spawn off more threads from other places, we need to create more static functions.  We also need to know at compile time what functions we are going to want to call in threads.  If we had a dozen possible entry points where we might want to spawn off a thread, the codebase could grow very large and very complex.</p>
<p>Fortunately, since we understand how to use pointer-to-member-functions, we have the benefit of another solution.  Consider the following code snippet:</p>
<p>
<font color="#a020f0">#include </font><font color="#ff00ff">&lt;iostream&gt;</font><br />
<font color="#a020f0">#include </font><font color="#ff00ff">&lt;string&gt;</font><br />
<font color="#a020f0">#include </font><font color="#ff00ff">&lt;pthread.h&gt;</font><br />
<font color="#a52a2a">using</font>&nbsp;<font color="#0000ff">namespace</font>&nbsp;std;</p>
<p>
<font color="#0000ff">class</font>&nbsp;example<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a">public</font>:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string s;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">void</font>&nbsp;say_hi()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;<font color="#ff00ff">&quot;hello &quot;</font>&lt;&lt;s&lt;&lt;endl;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">void</font>&nbsp;(example::*func())()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a">return</font>&nbsp;&amp;example::say_hi;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">void</font>&nbsp;get_hi()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">void</font>&nbsp;((example::*foo)()) =&nbsp;&nbsp;func();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<font color="#a52a2a">this</font>-&gt;*foo)();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">static</font>&nbsp;<font color="#0000ff">void</font>* thread_maker(<font color="#0000ff">void</font>* dat_s);<br />
};</p>
<p><font color="#0000ff">typedef</font>&nbsp;<font color="#0000ff">struct</font>&nbsp;val_st<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;example* e;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">void</font>&nbsp;(example::*func)();<br />
};</p>
<p><font color="#ff0000">//moved this out of the class definition since we need to reference val_st structure</font><br />
<font color="#0000ff">void</font>* example::thread_maker(<font color="#0000ff">void</font>* dat_s)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">struct</font>&nbsp;val_st* v = <font color="#a52a2a">static_cast</font>&lt;val_st*&gt;(dat_s);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;example* e = v-&gt;e;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">void</font>&nbsp;((example::*f)()) = v-&gt;func;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(e-&gt;*f)();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a">return</font>&nbsp;<font color="#ff00ff">NULL</font>;<br />
}</p>
<p><font color="#0000ff">int</font>&nbsp;main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pthread_t launch_thread;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;example foo;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;example bar;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val_st v;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo.s = <font color="#ff00ff">&quot;world&quot;</font>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bar.s = <font color="#ff00ff">&quot;there&quot;</font>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo.get_hi();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bar.get_hi();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">void</font>&nbsp;((example::*f)()) =&nbsp;&nbsp;bar.func();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(foo.*f)();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.e = &amp;foo;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.func = foo.func();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pthread_create(&amp;launch_thread, <font color="#ff00ff">NULL</font>, &amp;example::thread_maker, <font color="#a52a2a">static_cast</font>&lt;<font color="#0000ff">void</font>*&gt;(&amp;v));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pthread_join(launch_thread,<font color="#ff00ff">NULL</font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a">return</font>&nbsp;<font color="#ff00ff">0</font>;<br />
}<br />
</font>
</p>
<p>In this case, we consider what we know about pointer-to-member-functions, and the <strong>this</strong> pointer, and exploit this to vastly simplify a class that might have multiple thread entry points.  In order to do this, the first step is to add a structure to our application.  This structure contains a pointer to a member function, and the object to become that member-function&#8217;s <strong>this</strong> pointer.  This enables us to create a single static thread_maker function.  We pass our structure (cast as a void*) to this static function which is spawned off in it&#8217;s own thread.  We now have the ability to spawn off into a thread any arbitrary member function.  We can even decide at run time what functions to spawn off.  In performance-critical applications, we reduce the overhead of having layers-deep logic to bend all of our code around a single entry point, and trade off dozens or more functions with a single, slightly more difficult to read function.  We now have the ability to create pthreads in C++ in a fast, concise, and elegant manner.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tuxtips.org/?feed=rss2&amp;p=5</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
