Friday, 28 August 2009

PC-Lint and Visual Lint

Writing software is always a challenge. When you are responsible for every line of code across multiple products and platforms, it is critical to write solid code that is as good as possible (bugs are very expensive to deal with!) :)

The free lint tools (mainly cppcheck) are OK but seem to miss lots of things compared to the professional tools, and I've been meaning to get a proper static code analysis tool for a long time now...

So: I finally took the plunge a couple of days ago, and bought a license for PC-Lint. I'd been meaning to do this for a long time, having slowly been improving my tool chain. The longer I do programming, the more I realise that it is critical to have as good a set of tools as possible, from operating system, editor, IDE, shell/scripting tools etc. ...!

Having installed PC-Lint and started to use it... I soon realise how difficult it was to use, albeit very powerful. I have never seen a tool with so many command line options, and stepping from command line output to change the code (and back again) is very difficult. So, imagine my complete relief to stumble upon Visual Lint!

For those who don't know, Visual Lint it is a GUI front-end for PC-Lint that makes it a piece of cake to use; it integrates beautifully with Visual Studio.

One thing I like about the evaluation version of Visual Lint is that it makes it very easy for you to see which features you need, so you can end-up choosing the product variant that best meets your needs. I'm guessing I'll get the Professional Edition, and am still making my mind up; but I'm certain to get a copy in a few days.

It is a shame that PC-Lint doesn't have an evaluation model. The software is certainly expensive; which is understandable, but a shame as it prevents more people improving the quality of their code.

If only there were an integrated Static Code Analysis system for XCode on Mac. It seems that the availability of PC-Lint and Visual Lint gives a major advantage to Visual Studio on Windows for cross-platform coding, as much as I love the general speed of working on the Mac. I guess I'll continue to work on the Mac, but spend a little more time now on Windows analysing the cross-platform code I've written using Visual Lint.

Wednesday, 26 August 2009

auto_ptr with arrays - and a solution

It is pretty irritating that auto_ptr (a feature of C++, for those who don't know!) doesn't work with array variables.

In other words, it is not safe to do this:


int *pArray = new int[10];
auto_ptr autodel(pArray);


It is pretty easy however to create your own alternative to auto_ptr, that works with array pointers...

template <class T> class auto_ptr_array
{
public:
auto_ptr_array(T *p) :
mp(p)
{
}

~auto_ptr_array()
{
delete[] mp;
}

void reset(T *p)
{
delete []mp;
mp = p;
}

T *get()
{
return mp;
}

T* release()
{
T* lpRet = mp;
mp = NULL;
return lpRet;
}

private:
T *mp;
};


Example usage...

int main (int argc, char *argv[])
{
// Use it one of two ways...
auto_ptr_array autodel(new int[20]);
int *pval = autodel.get();

int *pval2 = new int[20];
auto_ptr_array autodel2(pval2);

printf ("Done!\n");

return 0;
}

Friday, 21 August 2009

Android NDK - getting STLPort up and running

If you want to get STLPort running with the Android NDK, you'll have a bit of work to do; especially if using Cygwin under Windows.

First, visit http://umbel.mooo.com/ and get the STLPort version from John Ripley (great job, John!). If you're a cygwin user, you'll first need to remember to install the git package.

Next thing is to copy the files to a place that works for you. On my system, I copied the files into my c:\android-ndk-1.5_r1 folder, and then moved the two hello-stl folders to somewhere that seemed consistent with the other NDK files:


C:\android-ndk-1.5_r1\apps\hello-stl
C:\android-ndk-1.5_r1\sources\samples\hello-stl


I then had to change a few files before I could build the STLPort...

setup.sh

Change the top few lines to look like this:

#!/bin/bash
if uname | grep -qi linux; then
export NDK_HOST=linux-x86
elif uname | grep -qi CYGWIN; then
export NDK_HOST=windows
else

export NDK_HOST=darwin-x86
fi

Change the third line up from the bottom to look like this:


ln -sf "$NDK_DIR/build/prebuilt/${NDK_HOST}/arm-eabi-4.2.1/bin/arm-eabi-$tool" arm-linux-$tool


stlport/build/lib/android.mak

Change the TOOLCHAIN_PREFIX line to look like this:


TOOLCHAIN_PREFIX := $(NDK_DIR)/build/prebuilt/$(NDK_HOST)/arm-eabi-4.2.1/bin/arm-eabi-


sources/samples/hello-stl/Android.mk

Change the STLPORT_BASE line to be this:


STLPORT_BASE := /cygdrive/c/android-ndk-1.5_r1/stlport


Change this:


LOCAL_LDLIBS += -L$(STLPORT_BASE)/build/lib/obj/gcc/so \
-lstlport


to this:


LOCAL_STATIC_LIBRARIES := libstlport.5.1





Building STLPort

Now that the files are merged-in, you're ready to build STLPort!

Run the following in the cygwin shell... it will build the STLPort static library for you! You'll only need to do this once.


export NDK_DIR=/cygdrive/c/android-ndk-1.5-r1
cd $NDK_DIR
./env.sh
./setup.sh


Now, do this to copy the file to your project:


cp -p \
/cygdrive/c/android-ndk-1.5_r1\stlport\build\lib\obj\gcc\ar\libstlport.5.1.a \
/cygdrive/c/android-ndk-1.5_r1\out\apps\hello-stl\android-1.5-arm





Building your project's shared library

You can now go back to the cygwin shell, and do this:


cd /cygdrive/c/android-ndk-1.5_r1
make APP=hello-stl


... which will build your shared library file:

C:\android-ndk-1.5_r1\apps\hello-stl\project\libs\armeabi\libhello-stl.so


Note that this will have the static STLPort library linked-in.

Building the hello-stl project

From Eclipse, use the New Project Wizard to create a new Android project for each sample, using the "Import from Existing Source" option and import the source from c:\android-ndk-1.5_r1\apps\hello-stl\project

You can now build and run your project. The string displayed comes from the shared library, using std::string ...!

Thursday, 20 August 2009

Android JNI/NDK - notes on getting started

There are a lot of steps required to get your Android development environment set-up, to a state where you can create your first Android "Hello World" app with JNI/NDK.

This is definitely not for the faint-hearted! It is complicated enough that I thought it'd be useful to run through in a blog entry.

So, here is a summary of what to do, in order to get started with using the Android software under both Mac and Windows.

1. Get the latest Sun Java SE Development Kit

Windows: You can get this from here:
http://java.sun.com/javase/downloads/index.jsp

Mac: You should already be up-to-date, assuming you have XCode installed

2. Get Eclipse

I downloaded the latest version of the "Eclipse IDE for Java Developers" from here:
http://www.eclipse.org/downloads/

Windows: Unzip, and then put a shortcut to eclipse.exe somewhere where you can find it!

Mac: Unstuff, and put Eclipse to your Applications folder.

3. Get the base Android SDK (1.5 or later!)

As we're doing to be doing NDK development, make sure you get Android 1.5 or later from here:

http://developer.android.com/sdk/index.html

Make sure you follow the appropriate instructions for installing/upgrading (depending on what current system you might already have)

Windows: When you unzip the file, make sure that it goes under the c:\ root folder... i.e. so it looks like this (for example):

c:\android-sdk-windows-1.5_r3


Mac: Put this under your home folder, so it looks like this (for example):

~/android-sdk-windows-1.5_r3


4. Windows: Get Cygwin

The cygwin toolchain is required for NDK development if you're using Windows.

So, make sure you have cygwin installed! You can get this from here:
http://www.cygwin.org
... note that you'll need the C/C++ developer tool packages.

Mac: users already have a suitable toolchain built-in through XCode.

5. Get the Android NDK

Get the latest Android NDK, from the "Native Development Tools" in the sidebar on in the sidebar on this page:
http://developer.android.com/sdk/index.html

Windows: When you unzip the files, make sure you copy them such that they are under the C:\ root folder, i.e. so that they look like this:

c:\android-ndk-1.5_r1

... if you leave them under e.g. My Documents, then the system will fail to build your source code due to spaces in the file paths etc.

Mac: Put this under your home folder, so it looks like this (for example):

~/android-ndk-1.5_r1


Make sure you follow the instructions that are in DOCS/INSTALL.TXT ...!!!

6. Windows: My Computer - path

Remember to follow instructions on setting your path variable!

Basically, append something like the following (which you'll have to change if you ever come to upgrade)


;c:\android-sdk-windows-1.5_r3;c:\android-ndk-1.5_r1


7. Create your first AVD

You can create your first AVD to be called something like my_android1.5 ... make sure you base it on the Android 1.5 SDK!

You can do this from Eclipse; and more information is available here:
http://developer.android.com/guide/developing/tools/avd.html

Test that you set-up the NDK properly

The following steps will create the following file:

out/apps/hello-jni/android-1.5-arm/libhello-jni.so


Windows:

start cygwin
cd /cygdrive/c/android-ndk-1.5_r1
make APP=hello-jni


Mac:

Run Terminal
cd ~/android-ndk-1.5_r1
make APP=hello-jni


8. Create your first basic Android Project

Now follow the instructions here:

http://developer.android.com/guide/developing/eclipse-adt.html#CreatingAProject


... and if you're lucky, it will build and run, and you can then get on with the JNI/NDK side of things!

9. Create and build/run your first NDK project

You can now create your first NDK project using JNI, and build/run it, following the steps you'll find here:

http://developer.android.com/sdk/ndk/1.5_r1/index.html#samples

Easy!

Using find with xargs in Linux/Mac/Unix/Cygwin with spaces in the file paths

I'm always having to perform searches through lots of files when on Mac/Linux/Cygwin

This is the style of command I'd normally use from the bash shell (Terminal) on Mac/Linux/Unix/Cygwin ...


find . -name "*.cpp" | xargs -- grep -i "find me" > q.q


This looks from the current folder (and all files below), searching for all files with the cpp file extension. For every file, it runs grep on it (case insensitively); putting the results of all searches in the file called q.q (which you can then edit using e.g. vim).

However, this simply doesn't work when the file or folder being searched has a space character in it. Which is annoyingly common in a files these days...

A short while back I discovered the solution to this "spaces in names/folders" problem, and I figured it'd be useful to write it up to save you the trouble...


find . -name "*.cpp" -print0 | xargs -0 -- grep -i "find me" > q.q


Note how we've added both -print0 and -0, which together magically solve the problem.

Incidentally, the -- in the argument list for xargs, is shell magic that tells xargs to ignore any options it might see after that point (e.g. the -i in the example), and simply pass them directly on to the command (grep in our example).

Tuesday, 18 August 2009

Android JNI NDK - and STL support?

There is an interesting post that you can find here, which indicates that it is possible to get STL support working in C++ code that you might want to port to the Android JNI / NDK, using STLPort. Cool!

This is really interesting; I think this was the biggest issue that was blocking a port of Mixtikl to Android devices (I think I can see a way around most other issues). So, I now need to clear some time in my schedule to investigate in more detail! :)

The STLPort info page has more details, and the license looks promising; all-in-all, this is very exciting!

Friday, 14 August 2009

Mixtikl ... V2!

We've put so much effort in to Mixtikl V1.5 ... and reworked so many things... that it seems to have evolved into Mixtikl V2. Right under our very eyes!

So, the release of the new version of Mixtikl is going to be quite a lot later than we planned early this year, but that is all part of the fun of designing and coding on the fly. You never know exactly where things will take you! :)

Right now we're focused on finishing off all the UI rework, and then fixing-up the bugs that the rework has (inevitably) introduced. I hope it is worth the wait!

GTK - how to enumerate widgets

I had fun recently trying to figure-out the code that would allow me to enumerate through all available GTK Widgets, a little bit like the Windows EnumWindows function. This took me a while to figure out... mainly because of the terrible state of the GTK documentation. :)

Anyways, here is the bare bones of the solution; as you can see, it is actually really easy.

A couple of things to note:
  • - a GtkWindow can be treated as a GtkWidget...!
  • - if a GtkWindow has child widgets, then it must be of type GTK_CONTAINER

static void widgetEnumerate (int nDepth, GtkWidget *pGtkWidget)
{
printf ("%d: Got GtkWidget=%x\n", nDepth, pGtkWidget);

// If the GtkWidget in question is a also a container,
// then we can enumerate through its children!
if (GTK_IS_CONTAINER(pGtkWidget)
{
GtkContainer *pGtkContainer = GTK_CONTAINER(pGtkWidget);
GList *pGtkWindowList = gtk_container_get_children(pGtkContainer);

GList *pNode;
for (pNode = pGtkWindowList; pNode != NULL; pNode = pNode->next)
{
GtkWidget *pGtkWidget = GTK_WIDGET(pNode->data);
widgetEnumerate(nDepth+1, pGtkWidget);
}
}
}

void enumerateGtkWidgets(void)
{
GList *pGtkWindowList = gtk_window_list_toplevels();
GList *pNode;
for (pNode = pGtkWindowList; pNode != NULL; pNode = pNode->next)
{
GtkWindow *pGtkWindow = GTK_WINDOW(pNode->pData);
widgetEnumerate(1, GTK_WIDGET(pGtkWindow));
}
}

Monday, 10 August 2009

iPhone - problems updating the Ad-Hoc Provisioning Profile

If you get the following error in XCode after having updated your Ad-Hoc provisioning profile...

CodeSign error: a valid provisioning profile is required

... then don't panic - help is at hand - here! :)

Friday, 7 August 2009

Porting from iPhone to Windows Mobile?

I found this article a couple of days back on the MSDN site - Porting the Amplitude Application from the iPhone to a Windows Mobile Device – a Case Study.

The article talks us through porting an iPhone app to Windows Mobile. This is a good idea of course - but the article decided to use C# as the language in which to completely rewrite the app for Windows mobile! This got me wondering why anybody would want to use anything other than C++ for writing applications (as much as I really like C# as a language), excepting of course those platforms where you have no choice.

The big thing about the iPhone - for me! - is that one of Apple's several great decisions was to adopt Cocoa as their platform. This means that apps are written in Objective-C ... and, if you want, you can use Objective-C++ as well. This means that all of your app code can be written in platform-neutral C++ ... with only the UI-specific code [which is based around the Cocoa Touch framework] being in Objective-C. This way, all of your non-UI code should be easy to port to any other platform that supports C++. Note: this approach assumes that you isolate and minimise your use of low-level Cocoa elements such as NSString as much as possible! This is easy to do if you use things like your own String adaptor classes, which wrap-up this platform specific stuff in a platform-neutral manner.

The nice thing about Windows Mobile is that all your code can be written in C++. So... why would you want to use a completely different language - C# in this case - as your language? Why not instead keep as much of your code as cross-platform as possible, and use C++, which is natively supported for Windows Mobile? Then you have to do much less work to port and maintain your application.

Oh well.

While doing some Android consultancy work recently, it was strange to reflect that all of the code had to be written in Java. I've got nothing against Java per se, it is just the annoying thought that all the code I wrote could not get re-used on other platforms. I can but hope that Android's NDK eventually matures to the point where we can write write most of our graphics code in C++.

As for Symbian - I won't look at that again until they base their development on a standard version of C++ with STL template support and Posix threads ... :)