<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>El Tramo | Cocoa</title>
  <subtitle>Remko Tronçon's Homepage</subtitle>
  <link href="http://el-tramo.be/blog/tag/cocoa/feed/" rel="self" type="application/rss+xml"/>
  <link href="http://el-tramo.be/"/>
  <updated>2012-05-19T12:29:42+02:00</updated>
  <id>http://el-tramo.be/</id>
  <author>
    <name>Remko Tronçon</name>
    <uri>http://el-tramo.be/about/</uri>
  </author>
  
  <entry>
    <title>Mixing Cocoa and Qt</title>
    <author>
      <name>Remko Tronçon</name>
      <uri>http://el-tramo.be/about/</uri>
    </author>
    <link href="http://el-tramo.be/blog/mixing-cocoa-and-qt"/>
    <updated>2008-08-16T00:00:00+02:00</updated>
    <id>http://el-tramo.be/blog/mixing-cocoa-and-qt</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://trolltech.com/products/qt/index&quot;&gt;Qt&lt;/a&gt; does a great job at abstracting out platform-specific features into platform-independent C++ APIs. However, sometimes you still need to write platform-specific code for features that are not in Qt (e.g. to access the platform&amp;rsquo;s address book),  or to access platform-specific applications (e.g. iTunes) or libraries (e.g. &lt;a href=&quot;http://sparkle.andymatuschak.org/&quot;&gt;Sparkle&lt;/a&gt;). On Mac OS X, almost all interfaces are offered through the &lt;a href=&quot;http://developer.apple.com/cocoa/&quot;&gt;Cocoa&lt;/a&gt; Objective-C interface, and the interfaces that are written in C++ have been deprecated and will disappear soon in favor of Cocoa. Although the language of Cocoa is different from Qt&amp;rsquo;s, Qt and &lt;a href=&quot;http://gcc.gnu.org&quot;&gt;GCC&lt;/a&gt; make it very easy to call these interfaces from within your application. In this post, I will show how this can be done by making an auto-updating application using Sparkle.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;To create our auto-updating application, we first lay down the auto-updater interface in a (pure) virtual class:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;class AutoUpdater {
  public:
    virtual void checkForUpdates() = 0;
};&lt;/pre&gt;
&lt;/blockquote&gt;


&lt;p&gt;The Sparkle implementation of this interface has the following C++ header:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;class SparkleAutoUpdater : public AutoUpdater {
  public:
    SparkleAutoUpdater(const QString&amp;amp; url);
    ~SparkleAutoUpdater();
    virtual void checkForUpdates();
  private:
    class Private;
    Private* d;
};&lt;/pre&gt;
&lt;/blockquote&gt;


&lt;p&gt;Note that I am using the &lt;a href=&quot;http://c2.com/cgi/wiki?PimplIdiom&quot;&gt;Pimpl&lt;/a&gt; idiom to hide Cocoa-specific internals from the API into a private internal class.&lt;/p&gt;

&lt;p&gt;The actual impementation of the &lt;code&gt;SparkleUpdater&lt;/code&gt; needs to call Sparkle&amp;rsquo;s Objective-C API. However, we cannot write the implementation in Objective-C, since the header for our updater (which will be included from within our application) is written in C++. Luckily, GCC&amp;rsquo;s Objective-C++ extension allows you to mix Objective-C with C++ without any problem. So, we create an Objective-C++ implementation of our updater, and put it in a &lt;code&gt;.mm&lt;/code&gt; file:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;class SparkleAutoUpdater::Private {
  public:
    SUUpdater* updater;
};

SparkleAutoUpdater::SparkleAutoUpdater(const QString&amp;amp; aUrl) {
  d = new Private;
  d-&amp;gt;updater = [[SUUpdater sharedUpdater] retain];
  NSURL* url = [NSURL URLWithString:
      [NSString stringWithUTF8String: aUrl.toUtf8().data()]];
  [d-&amp;gt;updater setFeedURL: url];
}

SparkleAutoUpdater::~SparkleAutoUpdater() {
  [d-&amp;gt;updater release];
  delete d;
}

void SparkleAutoUpdater::checkForUpdates() {
  [d-&amp;gt;updater checkForUpdatesInBackground];
}&lt;/pre&gt;
&lt;/blockquote&gt;


&lt;p&gt;All we do here is create an &lt;code&gt;SUUpdater&lt;/code&gt; (Sparkle&amp;rsquo;s updater class), set it up, and activate it in our &lt;code&gt;checkForUpdates()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;To integrate Objective-C++ classes into a Qt project, &lt;code&gt;qmake&lt;/code&gt; provides the &lt;code&gt;OBJECTIVE_SOURCES&lt;/code&gt; variable. Knowing this, we add our new classes to our &lt;code&gt;qmake&lt;/code&gt; project file:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;HEADERS += AutoUpdater.h
SOURCES += AutoUpdater.cpp
mac {
  HEADERS += SparkleAutoUpdater.h
  OBJECTIVE_SOURCES += SparkleAutoUpdater.mm
  LIBS += -framework Sparkle
}&lt;/pre&gt;
&lt;/blockquote&gt;


&lt;p&gt;Before we integrate the updater into our application, there is still one detail we have to take care of: if you write Objective-C code that creates objects, you need to instantiate an &lt;code&gt;NSAutoReleasePool&lt;/code&gt; to enable Cocoa&amp;rsquo;s memory management. Although we could do this in &lt;code&gt;SparkleAutoUpdater&lt;/code&gt;, we&amp;rsquo;re going to put this in a separate initializer class, so we can share this with other Objective-C++ implementations in our application. The body of this class looks as follows:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;class CocoaInitializer::Private {
  public:
    NSAutoreleasePool* autoReleasePool;
};

CocoaInitializer::CocoaInitializer() {
  d = new CocoaInitializer::Private();
  NSApplicationLoad();
  d-&amp;gt;autoReleasePool = [[NSAutoreleasePool alloc] init];
}

CocoaInitializer::~CocoaInitializer() {
  [d-&amp;gt;autoReleasePool release];
  delete d;
}&lt;/pre&gt;
&lt;/blockquote&gt;


&lt;p&gt;Now all that&amp;rsquo;s left to do is integrate all this into our application:&lt;/p&gt;

&lt;blockquote&gt;&lt;code&gt; &lt;/code&gt;
&lt;pre&gt;int main(int argc, char* argv[]) {
  ...
  AutoUpdater* updater = 0;
#ifdef Q_WS_MAC
  CocoaInitializer cocoaInitiarizer;
  updater = new SparkleUpdater(&quot;http://el-tramo.be/myapp/appcast.xml&quot;);
#endif
  ...
  if (updater) {
    updater-&amp;gt;checkForUpdates();
  }
  ...
}&lt;/pre&gt;
&lt;/blockquote&gt;


&lt;p&gt;That&amp;rsquo;s it! If you want to try this out yourself, just download the &lt;a href=&quot;http://el-tramo.be/files/blog/mixing-cocoa-and-qt/mixing-cocoa-and-qt.zip&quot;&gt;sources&lt;/a&gt; of this mini-project, build them, and off you go. Don&amp;rsquo;t forget to remove &lt;code&gt;~/Library/Preferences/be.el-tramo.mixing-cocoa-and-qt.plist&lt;/code&gt; to clear Sparkle&amp;rsquo;s state cache.&lt;/p&gt;
</content>
  </entry>
  
</feed>

