<?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>All Things Scurrilous &#187; Software</title>
	<atom:link href="http://www.scurrilous.com/blog/archives/category/computers/software/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.scurrilous.com/blog</link>
	<description>What does it mean to be scurrilous? I'll try to demonstrate...</description>
	<lastBuildDate>Tue, 13 Dec 2011 21:57:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Syncing large file libraries over the Internet</title>
		<link>http://www.scurrilous.com/blog/archives/2011/08/23/syncing-large-file-libraries-over-the-internet/</link>
		<comments>http://www.scurrilous.com/blog/archives/2011/08/23/syncing-large-file-libraries-over-the-internet/#comments</comments>
		<pubDate>Tue, 23 Aug 2011 23:27:06 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.scurrilous.com/blog/?p=198</guid>
		<description><![CDATA[With the demise of FolderShare, I&#8217;ve found it rather difficult to keep my music library synchronized between home and the office. While there is software you can buy like SuperSync, you can pretty easily achieve a more general solution using free software, with the added benefit of universal OS support (e.g. Windows, Mac OS X, [...]]]></description>
			<content:encoded><![CDATA[<p>With the demise of <a href="http://en.wikipedia.org/wiki/Windows_Live_Mesh#FolderShare_and_Windows_Live_Sync">FolderShare</a>, I&#8217;ve found it rather difficult to keep my music library synchronized between home and the office. While there is software you can buy like <a href="http://www.supersync.com/">SuperSync</a>, you can pretty easily achieve a more general solution using free software, with the added benefit of universal OS support (e.g. Windows, Mac OS X, <em>and</em> Linux).</p>
<p>First, for connectivity between private LANs across the Internet, <a href="https://secure.logmein.com/products/hamachi/download.aspx">Hamachi</a> works very well (and is free for non-commercial use). It&#8217;s supported on Windows and OS X, and <a href="https://secure.logmein.com/US/labs/">in beta for Linux and Windows Mobile</a>. Just install the client on each machine, and you&#8217;ll have a virtual IP address that you can use to securely tunnel over the Internet to other machines in your mesh using any application. I created a LogMeIn account to use Managed mode which (obviously) makes management easier, but Unmanaged mode works as well.</p>
<p>Next, you can use <a href="http://www.samba.org/ftp/rsync/rsync.html">rsync</a> to efficiently copy and synchronize files through the Hamachi tunnel. It&#8217;s usually already installed on Linux and OS X, and can be easily installed on Windows using the <a href="http://www.cygwin.com/">Cygwin</a> <a href="http://cygwin.com/setup.exe">installer</a>.</p>
<p>While Hamachi makes it easy to browse Windows shares (assuming you&#8217;re running Windows) via the tunnel, or even rsync them using a UNC path, the <a href="http://en.wikipedia.org/wiki/Server_Message_Block">SMB</a> protocol is glacially slow. Therefore, you&#8217;ll want to set up the rsync daemon on the machine containing your authoritative version. (While rsync can easily provide two-way synchronization, it is much less risky and mentally taxing to treat one copy as authoritative and access it using a read-only rsync share.) To configure the daemon, you&#8217;ll need to create a file called <a href="http://www.samba.org/ftp/rsync/rsyncd.conf.html">/etc/rsyncd.conf</a> that specifies global and per-library options. On Windows, to share a music library in M:\Music, the file would look like this:</p>
<p><code>use chroot = false<br />
strict modes = false</p>
<p>[Music]<br />
path = /cygdrive/M/Music<br />
read only = true</code></p>
<p>Then you can fire up the rsync daemon simply by running <code>rsync --daemon</code> from a shell, command prompt, Run dialog (Windows+R), etc. rsync won&#8217;t output anything, but you can verify in your process/task manager that it&#8217;s running. If you want the rsync daemon to run automatically as a Windows service, that can be done using <a href="http://web.mit.edu/cygwin/cygwin_v1.3.2/usr/doc/Cygwin/cygrunsrv.README">cygrunsrv</a>, but you&#8217;ll have to refer <a href="http://www.gaztronics.net/rsync.php">elsewhere</a> for instructions.</p>
<p>Finally, to actually sync the library to a client, you&#8217;ll need to enter a slightly gnarly rsync command (which the difficulty of remembering inspired this blog post) on the client:</p>
<p><code>rsync -rtOh --chmod=ugo=rwX --ignore-existing --delete --progress rsync://&lt;server IP from Hamachi client&gt;/Music/* /cygdrive/c/Music</code></p>
<p>This command will copy the everything in the Music module (defined above as M:\Music) to C:\Music, deleting anything in C:\Music that doesn&#8217;t exist in M:\Music. Refer to the <a href="http://www.samba.org/ftp/rsync/rsync.html">rsync man page</a> for details on these options and others, but here&#8217;s a brief explanation:</p>
<ul>
<li>-r, &#8211;recursive: recurse into directories</li>
<li>-t, &#8211;times: preserve modification times (to aid future synchronization)</li>
<li>-O, &#8211;omit-dir-times: omit directories from &#8211;times</li>
<li>-h, &#8211;human-readable: output numbers in a human-readable format (we&#8217;re humans, right?)</li>
<li>&#8211;chmod=ugo=rwX: give new files the destination-default permissions (otherwise they&#8217;ll end up with screwy permissions)</li>
<li>&#8211;ignore-existing: skip updating files that already exist on the destination (unless you want things like MP3 tag changes to trigger lots of delta transfers)</li>
<li>&#8211;delete: delete extraneous files from the receiving side (to avoid accumulating duplicates when files are renamed on the sender)</li>
<li>&#8211;progress: print information showing the progress of the transfer (since it will probably take a long time to sync your whole media library)</li>
</ul>
<p><strong>Note: For your first attempt, you&#8217;ll probably want to also include the <code>-n</code> option, which executes a dry-run, so you don&#8217;t accidentally end up deleting files you didn&#8217;t intend to.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.scurrilous.com/blog/archives/2011/08/23/syncing-large-file-libraries-over-the-internet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Easily centralize a local Git repository</title>
		<link>http://www.scurrilous.com/blog/archives/2011/07/16/centralize-local-git-repository/</link>
		<comments>http://www.scurrilous.com/blog/archives/2011/07/16/centralize-local-git-repository/#comments</comments>
		<pubDate>Sat, 16 Jul 2011 21:28:07 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.scurrilous.com/blog/?p=184</guid>
		<description><![CDATA[If you&#8217;re like me (and condolences if you are), you&#8217;ve often started a local Git repository for a new project, and then later wanted to create a shared upstream repository on another computer. (GitHub walks you through this, but let&#8217;s assume you want to manage the shared repository yourself.) Before I knew Git very well, [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re like me (and condolences if you are), you&#8217;ve often started a local Git repository for a new project, and then later wanted to create a shared upstream repository on another computer. (<a href="http://help.github.com/create-a-repo/">GitHub walks you through this</a>, but let&#8217;s assume you want to manage the shared repository yourself.) Before I knew Git very well, I did this clumsily by copying the .git directory and tweaking its config file and permissions (which was especially difficult when moving from a Windows desktop to a Linux server). But that is very un-Git; here&#8217;s a much better method:</p>
<p>On the upstream server, go to where you want the repository to be located and create a bare, shared repository:</p>
<p><code>$ cd /var/git<br />
$ git init --bare --shared myrepo.git</code></p>
<p>Then on your local machine, simply push the local repository up to the new shared repository with the <code>-u</code> option:</p>
<p><code>$ git push -u ssh://myuser@myserver/var/git/myrepo.git master</code></p>
<p>The <code>-u</code> option is short for <code>--set-upstream</code>. From the <a href="http://kernel.org/pub/software/scm/git/docs/git-push.html">git-push</a> man page:</p>
<blockquote><p>For every branch that is up to date or successfully pushed, add upstream (tracking) reference, used by argument-less git-pull(1) and other commands.</p></blockquote>
<p>Now with just two Git commands, your local repository acts just like you&#8217;d cloned it from your new shared repository.</p>
<p>Note: If you have a group of users that you want to be able to modify the repository, ensure that your top-level git directory is owned by that group and the group sticky bit is set in the permissions. For example:</p>
<p><code>$ chgrp -R git /var/git<br />
$ chmod -R g+w /var/git<br />
$ chmod g+s /var/git<br />
$ ls -ld /var/git<br />
drwxrw<u>s</u>rwx 22 git <u>git</u> 4.0K Jul 16 12:00 /var/git</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.scurrilous.com/blog/archives/2011/07/16/centralize-local-git-repository/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Putting UTF-8 into C/C++ Source Code</title>
		<link>http://www.scurrilous.com/blog/archives/2009/11/05/putting-utf-8-into-c-source/</link>
		<comments>http://www.scurrilous.com/blog/archives/2009/11/05/putting-utf-8-into-c-source/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 23:07:24 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.scurrilous.com/blog/?p=154</guid>
		<description><![CDATA[After much googling, I could not find any tools for converting a UTF-8 string into an escaped C/C++ string literal suitable for pasting into an ASCII source file. Therefore I produced this Perl script which seems to provide a fairly readable escaped string: use strict; chomp; print '"'; my $prev_esc = 0; print map { [...]]]></description>
			<content:encoded><![CDATA[<p>After much googling, I could not find any tools for converting a <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8</a> string into an escaped C/C++ string literal suitable for pasting into an ASCII source file. Therefore I produced this Perl script which seems to provide a fairly readable escaped string:</p>
<pre>use strict;
chomp;
print '"';
my $prev_esc = 0;
print map
    {
        if (ord $_ > 0x7f) {
            $prev_esc = 1;
            sprintf('\\x%lx', ord $_);
        } else {
            my $need_break = $prev_esc &#038;&#038; /[0-9A-Fa-f]/;
            $prev_esc = 0;
            ($need_break ? '" "' : '') . $_;
        }
    }
    split('', $_);
print '"' . "\n";
</pre>
<p>Run it with the Perl -n option, and it will output an escaped string literal for each line input:</p>
<pre>$perl -n utf8esc.pl
<a href="http://www.columbia.edu/kermit/utf8.html">Grüße aus Bärenhöfe</a>
"Gr\xc3\xbc\xc3\x9f" "e aus B\xc3\xa4renh\xc3\xb6" "fe"
</pre>
<p>Hit Ctrl-D on a blank line to exit.</p>
<p>Unfortunately, C/C++ seems to have the strange rule that all hex characters following a &#8220;\x&#8221; apply to that escape sequence, even though the maximum value allowed is 0xff. Therefore it is necessary to break the string into separate segments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.scurrilous.com/blog/archives/2009/11/05/putting-utf-8-into-c-source/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Build Boost 1.39 for 64-bit Windows</title>
		<link>http://www.scurrilous.com/blog/archives/2009/05/07/build-boost-139-for-64-bit-windows/</link>
		<comments>http://www.scurrilous.com/blog/archives/2009/05/07/build-boost-139-for-64-bit-windows/#comments</comments>
		<pubDate>Thu, 07 May 2009 09:34:01 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.scurrilous.com/blog/?p=142</guid>
		<description><![CDATA[Building Boost for 64-bit Windows turns out not to be completely straightforward. These instructions assume you&#8217;re using Visual Studio 2008 and running from a VS 2008 x64 Command Prompt. First, running bootstrap.bat appears to fail: Building Boost.Jam build engine Failed to build Boost.Jam build engine. Please consult bjam.log for furter diagnostics. You can try to [...]]]></description>
			<content:encoded><![CDATA[<p>Building <a href="http://www.boost.org/">Boost</a> for 64-bit Windows turns out not to be completely straightforward. These instructions assume you&#8217;re using Visual Studio 2008 and running from a VS 2008 x64 Command Prompt.</p>
<p>First, running bootstrap.bat appears to fail:</p>
<p><code>Building Boost.Jam build engine</p>
<p>Failed to build Boost.Jam build engine.<br />
Please consult bjam.log for furter diagnostics.</p>
<p>You can try to obtain a prebuilt binary from</p>
<p>http://sf.net/project/showfiles.php?group_id=7586&#038;package_id=72941</p>
<p>Also, you can file an issue at http://svn.boost.org<br />
Please attach bjam.log in that case.</code></p>
<p>Actually, it&#8217;s not failing to build, it&#8217;s just trying to copy the executable from the wrong path. All you need to do is copy tools\jam\src\bin.ntx86<strong>_64</strong>\bjam.exe to the top-level Boost directory.</p>
<p>Next, you need to install any of the optional libraries you want to support. For Python support, you can install the <a href="http://www.python.org/download/releases/2.6.2/">Windows AMD64 MSI Installer</a>, and then add the install directory (C:\Python26 by default) to your PATH. For Graphviz parsing support, download and unzip <a href="http://expat.sourceforge.net/">Expat 2.0.1</a> and my <a href="http://www.scurrilous.com/projects/expat-vs2008-x64.zip">VS 2008 x64 project files</a>, then use Batch Build in VS 2008 to build the x64 targets. You&#8217;ll also need to rename the Expat library reference in Boost&#8217;s libs\graph\build\Jamfile.v2 from &#8220;expat&#8221; to &#8220;libexpat&#8221;.</p>
<p>Finally, run the following commands to build Debug and Release DLLs, setting the Expat paths appropriately and the -j option to the number of processor cores you have:</p>
<p><code>set EXPAT_INCLUDE=C:\expat-2.0.1\lib</p>
<p>set EXPAT_LIBPATH=C:\expat-2.0.1\win64\bin\Debug<br />
bjam -j3 --stagedir=stage64 --without-mpi toolset=msvc address-model=64 variant=debug link=shared threading=multi runtime-link=shared stage > build-shared-multi-debug64.log</p>
<p>set EXPAT_LIBPATH=C:\expat-2.0.1\win64\bin\Release<br />
bjam -j3 --stagedir=stage64 --without-mpi toolset=msvc address-model=64 variant=release link=shared threading=multi runtime-link=shared stage > build-shared-multi-release64.log</code></p>
<p>With any luck, in about 5-15 minutes, you&#8217;ll have a set of DLLs and import libraries in stage64/lib. The build generates lots of output and warnings, which is the reason for redirecting the output to a file, but you&#8217;ll want to check the beginning and end of each log to make sure it built everything you expected.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.scurrilous.com/blog/archives/2009/05/07/build-boost-139-for-64-bit-windows/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Expat 2.0.1 for 64-bit Windows</title>
		<link>http://www.scurrilous.com/blog/archives/2009/05/07/expat-201-for-64-bit-windows/</link>
		<comments>http://www.scurrilous.com/blog/archives/2009/05/07/expat-201-for-64-bit-windows/#comments</comments>
		<pubDate>Thu, 07 May 2009 09:06:54 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.scurrilous.com/blog/?p=138</guid>
		<description><![CDATA[I couldn&#8217;t find any instructions for building Expat for 64-bit Windows (x64), so I updated the 32-bit projects files myself: expat-vs2008-x64.zip. See my projects page for brief usage instructions.]]></description>
			<content:encoded><![CDATA[<p>I couldn&#8217;t find any instructions for building <a href="http://expat.sourceforge.net/">Expat</a> for 64-bit Windows (x64), so I updated the 32-bit projects files myself: <a href="http://www.scurrilous.com/projects/expat-vs2008-x64.zip">expat-vs2008-x64.zip</a>. See my <a href="http://www.scurrilous.com/projects/">projects page</a> for brief usage instructions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.scurrilous.com/blog/archives/2009/05/07/expat-201-for-64-bit-windows/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Windows Update Finally Working</title>
		<link>http://www.scurrilous.com/blog/archives/2008/04/27/windows-update-finally-working/</link>
		<comments>http://www.scurrilous.com/blog/archives/2008/04/27/windows-update-finally-working/#comments</comments>
		<pubDate>Sun, 27 Apr 2008 21:57:38 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.scurrilous.com/blog/archives/2008/04/27/windows-update-finally-working/</guid>
		<description><![CDATA[When I got my iPhone 6 months ago, I had to upgrade vile and hated iTunes to activate it. After the iTunes upgrade, it wanted me to restart the computer. When the system booted back up (and on every subsequent reboot), there was a crash in userinit.exe. Unable to find any trace of a surgical [...]]]></description>
			<content:encoded><![CDATA[<p>When I got my iPhone 6 months ago, I had to upgrade vile and hated iTunes to activate it. After the iTunes upgrade, it wanted me to restart the computer. When the system booted back up (and on every subsequent reboot), there was a crash in userinit.exe. Unable to find any trace of a surgical solution on the web, I resorted to the blunt solution: reinstall Windows (in place).</p>
<p>After reinstalling, the userinit.exe crash went away, but then a new problem surfaced that has plagued me constantly until today: Windows Update fails on all updates. Back when the problem first occurred, I could find no solution that mentioned the particular problem, which surfaced as error 80246002 or &#8220;AUClnt	FATAL: Error: 0&#215;80004002. wuauclt handler: failed to spawn COM server&#8221; in C:\WINDOWS\WindowsUpdate.log. At long last, thanks to <a href="http://www.eggheadcafe.com/software/aspnet/30563544/windowsupdate-failed-afte.aspx">this page</a>, I found the solution, <a href="http://support.microsoft.com/kb/943144">KB943144</a>, posted October 26, 2007. The short answer:</p>
<blockquote><p>net stop wuauserv<br />
regsvr32 %windir%\system32\wups2.dll<br />
net start wuauserv</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.scurrilous.com/blog/archives/2008/04/27/windows-update-finally-working/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>myFairTunes</title>
		<link>http://www.scurrilous.com/blog/archives/2007/11/21/myfairtunes/</link>
		<comments>http://www.scurrilous.com/blog/archives/2007/11/21/myfairtunes/#comments</comments>
		<pubDate>Wed, 21 Nov 2007 21:35:20 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.scurrilous.com/blog/archives/2007/11/21/myfairtunes/</guid>
		<description><![CDATA[I&#8217;m very excited to find that it&#8217;s not difficult at all to remove iTunes DRM from songs purchased from the iTunes Music Store. myFairTunes will convert all your purchased music from M4P to M4A in place, add it back to your iTunes library, and optionally back up the M4P files to another folder and remove [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m very excited to find that it&#8217;s not difficult at all to remove iTunes DRM from songs purchased from the iTunes Music Store. myFairTunes will convert all your purchased music from M4P to M4A in place, add it back to your iTunes library, and optionally back up the M4P files to another folder and remove them from iTunes. Since my primary music computer has trouble syncing my iPhone, it&#8217;s very helpful to be able to move the music to another computer that doesn&#8217;t have as much sync trouble.</p>
<p><a href="http://sourceforge.net/projects/myfairtunes">myFairTunes on SourceForge</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.scurrilous.com/blog/archives/2007/11/21/myfairtunes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++ Functors</title>
		<link>http://www.scurrilous.com/blog/archives/2007/01/23/cpp-functors/</link>
		<comments>http://www.scurrilous.com/blog/archives/2007/01/23/cpp-functors/#comments</comments>
		<pubDate>Tue, 23 Jan 2007 08:28:34 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.scurrilous.com/blog/archives/2007/01/23/c-functors/</guid>
		<description><![CDATA[People have asked me several times what I think of &#8220;functors&#8221; in C++, so I decided to form an opinion (and write it down somewhere that myself and others can refer to). I&#8217;ve also always meant to include more technical content in this blog&#8230; My reference material on the subject was an article Chuck provided, [...]]]></description>
			<content:encoded><![CDATA[<p>People have asked me several times what I think of &#8220;functors&#8221; in C++, so I decided to form an opinion (and write it down somewhere that myself and others can refer to). I&#8217;ve also always meant to include more technical content in this blog&#8230;</p>
<p>My reference material on the subject was an article Chuck provided, <a href="http://www.tutok.sk/fastgl/callback.html">Callbacks in C++ Using Template Functors</a>. I felt that while it&#8217;s true that all of the functor alternatives shown in the article are obviously undesirable according to the criteria listed (and perhaps other more basic criteria, such as code readability), it doesn&#8217;t really seem to show an example of the interface-oriented (i.e. pure virtual class) model, which I believe is the purest way to solve the problem. (By pure, I mean satisfying criteria such as being object-oriented, type-safe, and non-coupled, yet not relying on <tt>void*</tt> casts and template wizardry.) Here is the example that I feel was omitted:</p>
<pre>class Notifiable
{
public:
    virtual void notify() = 0;
}

class Button
{
public:
    void click() { if (m_pnOnClick) m_pnOnClick->notify(); }
    void onClick(Notifiable* pn) { m_pnOnClick = pn; }
private:
    Notifiable* m_pnOnClick;
}

class CDPlayer
{
public:
    void play();
    void stop();
}

class CDPlayNotifiable : public Notifiable
{
public:
    CDPlayNotifiable(CDPlayer* cdp) : m_cdp(cdp) { }
    virtual void notify() { m_cdp->play(); }
private:
    CDPlayer* m_cdp;
}

class CDStopNotifiable : public Notifiable
{
public:
    CDStopNotifiable(CDPlayer* cdp) : m_cdp(cdp) { }
    virtual void notify() { m_cdp->stop(); }
private:
    CDPlayer* m_cdp;
}

void main()
{
    CDPlayer cdp;
    CDPlayNotifiable pn(&#038;cdp);
    CDStopNotifiable sn(&#038;cdp);
    Button playButton;
    playButton.onClick(&#038;pn);
    Button stopButton;
    stopButton.onClick(&#038;sn);
    // ...
}
</pre>
<p>I believe this satisfies all but one of the &#8220;Criteria for a Good Callback Mechanism&#8221; mentioned in the article: object-oriented, type-safe, non-coupling, non-type-intrusive, and flexible. The remaining criterion, being &#8220;generic&#8221;, is of questionable validity. Obviously it&#8217;s desirable not to require the user to write repetitive support code, but I think there&#8217;s some value to explicitly defining interfaces and being able to write custom binding code. Consider, for instance, how most UI frameworks include an argument on their events that identifies the sending object. If the functor of the Button class in the article included this argument, you could no longer directly bind it directly to <tt>CDPlayer::play()</tt>.</p>
<p>However, the code above sucks in C++ for two reasons: 1) There&#8217;s no shorthand way to provide implementations of Notifiable. (Anonymous classes in Java are great for this.) 2) Managing the lifetime of the Notifiable objects is difficult. (Again, with GC in Java, this is not an issue.) In my example, I used pointers, which necessitates ensuring that the Notifiable objects exist at least as long as the Buttons referencing them. In the functor article, this is accomplished by the functors being held by value. This makes sense for functors, which are known to be small and non-polymorphic and to implement a default constructor and <tt>operator=()</tt>. Objects implementing Notifiable may or may not be small, but more importantly, they are polymorphic and therefore cannot be held by value.</p>
<p>Given these difficulties, functors do seem to be a reasonable mechanism for handling callbacks in C++. I&#8217;m curious whether the <tt>memcpy()</tt> on the pointer-to-member-function in FunctorBase is kosher with regard to the C++ standard, but even if it&#8217;s not, it&#8217;s the sort of thing that always tends to work anyway.</p>
<p>BTW, in Java, the above code directly translates to this, which seems pretty much ideal to me:</p>
<pre>interface Notifiable
{
    void notify();
}

class Button
{
    public void click() { if (m_onClick != null) m_onClick.notify(); }
    public void onClick(Notifiable n) { m_onClick = n; }

    private Notifiable m_onClick;
}

class CDPlayer
{
    public void play();
    public void stop();
}

void main()
{
    final CDPlayer cdp = new CDPlayer();
    Button playButton = new Button();
    playButton.onClick(new Notifiable() { public void notify() { cdp.play(); } });
    Button stopButton = new Button();
    stopButton.onClick(new Notifiable() { public void notify() { cdp.stop(); } });
    // ...
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.scurrilous.com/blog/archives/2007/01/23/cpp-functors/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Jove in EE Times</title>
		<link>http://www.scurrilous.com/blog/archives/2005/11/07/jove-in-ee-times/</link>
		<comments>http://www.scurrilous.com/blog/archives/2005/11/07/jove-in-ee-times/#comments</comments>
		<pubDate>Mon, 07 Nov 2005 20:45:29 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.scurrilous.com/blog/archives/2005/11/07/jove-in-ee-times/</guid>
		<description><![CDATA[EE Times printed an article today about Jove. It has several quotes from me, gathered from our 45 minute interview, though as you might expect, they really zeroed in on the few somewhat inflammatory ones: &#8220;It really didn&#8217;t seem like Vera was justified as a separate language,&#8221; Robinson said. &#8220;It had no tools and no [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.eetimes.com/">EE Times</a> printed <a href=" http://www.eetimes.com/showArticle.jhtml?articleID=173403258">an article</a> today about <a href="http://jove.sourceforge.net/">Jove</a>. It has several quotes from me, gathered from our 45 minute interview, though as you might expect, they really zeroed in on the few somewhat inflammatory ones:</p>
<blockquote><p>&#8220;It really didn&#8217;t seem like Vera was justified as a separate language,&#8221; Robinson said. &#8220;It had no tools and no libraries, it had a lot of bugs, and it ran pretty slow.&#8221; Another issue was limited reporting capabilities for functional coverage. &#8220;What took us a couple of weeks in Vera took a day in Java,&#8221; Robinson said.</p></blockquote>
<p>Oh well, I guess that is how I feel about Vera.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.scurrilous.com/blog/archives/2005/11/07/jove-in-ee-times/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Europeans Of The Year</title>
		<link>http://www.scurrilous.com/blog/archives/2005/10/31/europeans-of-the-year/</link>
		<comments>http://www.scurrilous.com/blog/archives/2005/10/31/europeans-of-the-year/#comments</comments>
		<pubDate>Mon, 31 Oct 2005 17:18:55 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Politics]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.scurrilous.com/blog/?p=99</guid>
		<description><![CDATA[Unless you&#8217;re totally xenophobic, you should consider voting for the Europeans of the Year, organized by the European Voice magazine, which &#8220;casts a spotlight on 50 individuals who have most influenced the European legislative and political agenda during the preceding year&#8221;. (They have to be European, but you don&#8217;t.) I took interest in this poll [...]]]></description>
			<content:encoded><![CDATA[<p>Unless you&#8217;re totally xenophobic, you should consider voting for the <a href="http://www.ev50.com/noflash/">Europeans of the Year</a>, organized by the <a href="http://www.europeanvoice.com/">European Voice</a> magazine, which &#8220;casts a spotlight on 50 individuals who have most influenced the European legislative and political agenda during the preceding year&#8221;. (They have to be European, but you don&#8217;t.)</p>
<p>I took interest in this poll because one of the nominees, Florian Müller, is the founder of <a href="http://www.nosoftwarepatents.com/">NoSoftwarePatents.com</a>, which is a cause very important to me. In addition to recognizing his efforts, a win for Müller would also do much to promote the cause. Because the poll requires voting in all 10 different areas, I found the <a href="http://www.nosoftwarepatents.com/en/m/ev50/vote.html">NoSoftwarePatents.com voting guide</a> helpful.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.scurrilous.com/blog/archives/2005/10/31/europeans-of-the-year/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

