C++ on iPhone: Part 2, Exceptions

In part 2 of this C++ on iPhone series I’ll be exploring C++ exception handling support, and as a bonus I’ll touch on use of standard C++ lib console output stream, as well as showing a way to call C++ code from Objective C. As a reminder, exception handling is normally one of the weak spots in "mobile device" C++ support, so I wanted to find out how well it is supported on iPhone.

Jumping right into some code, using the same Xcode project as in part 1, I added a new C++ class Exceptions (adding Exceptions.cpp and Exceptions.h to the project).

Exceptions.h looks like this:

1
2
3
4
5
6
7
8
9
#include <exception>
#include <iostream>
using namespace std;
 
class Exceptions
{
public:
	static void test(int whichException);
};

This is a very simple class with just one static member function used to exercise exception handling support. The only noteworthy thing here is that some of the C++ standard library features are used, namely the #includes of <iostream> (used here to output logging information to the console) and <exception> which is a base class intended to be sub-classed by applications. Additionally, we need to specify "using namespace std " to avoid specifying the "std:: " prefix on all standard C++ library classes.

Exceptions.cpp looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#import &quot;Exceptions.h&quot;
#import &quot;ExceptionsBridge.h&quot;
 
void exceptionTest()
{
	Exceptions::test(1);
	Exceptions::test(2);
	Exceptions::test(3);
	Exceptions::test(4);
}
 
class MyException1 : public exception
{
	virtual const char* what() const throw()
	{
		return &quot;MyException1 was thrown&quot;;
	}
} myException1;
 
class MyException2 : public exception
{
	virtual const char* what() const throw()
	{
		return &quot;MyException2 was thrown&quot;;
	}
} myException2;
 
class MyException3 : public exception
{
	virtual const char* what() const throw()
	{
		return &quot;MyException3 was thrown&quot;;
	}
} myException3;
 
class BadException : public exception
{
	virtual const char* what() const throw()
	{
		return &quot;BadException was thrown&quot;;
	}
} badException;
 
void Exceptions::test(int whichException)
{
	try
	{
		switch(whichException) {
		case 1:
			throw myException1;
		case 2:
			throw myException2;
		case 3:
			throw myException3;
		default:
			throw badException;
		}
	}
	catch (exception&amp; e)
	{
		cout &lt;&lt; e.what() &lt;&lt; endl;
	}
}

There are a number of things happening here. First, you’ll notice the #include of ExceptionsBridge.h , more on this later. We also derive 4 custom classes from the standard library "exception " base class, namely MyException1-3 and BadException . These are declared and instantiated in place using the declarators myException1-3 and badException respectively.

We also implement the static Exceptions::test() method, which simply takes an int parameter and uses it to decide which exception type to throw. The throws are wrapped in a try{} block, with a corresponding catch{exception&} statement, which catches a reference to the base exception class, so that all thrown exceptions are caught internally. The catch block also writes log output to cout which is a standard C++ library console output stream.

We also implement the C-style method exceptionTest() at global scope, the definition looks like this:

1
2
3
4
5
6
7
void exceptionTest()
{
	Exceptions::test(1);
	Exceptions::test(2);
	Exceptions::test(3);
	Exceptions::test(4);
}

The exceptionTest() method simply calls Exception::test() with various parameters and is not part of a class, so is callable from C language. In order to do this we use the ExceptionsBridge.h file which is included both from the C++ side (in Exceptions.cpp ) and from the Objective C side (in main.m , as we’ll see shortly).

The ExceptionsBridge.h file looks like this:

#ifdef __cplusplus
extern "C" {
#endif

void exceptionTest();

#ifdef __cplusplus
}
#endif

This is the secret sauce that provides a way for Objective-C code to communicate with C++ code. In order for the exceptionTest() method to be visible from Objective C code, we need to do two things: i) declare the method as extern "C" from the C++ side (this will provide an unmangled symbol export to make the method visible to Objective C), and ii) forward declare the method from the Objective C side (so that the compiler knows it is external and will be resolved at link time). This header accomplishes both by using the preprocessor to test the compiler defined symbol __cplusplus , which is only defined when compiling a C++ file. A bridging header like this could be used to bridge all touch points between Objective C and C++ code (though there are other ways to do this using Objective C++ features, which I plan to cover in a future article).

Then, to complete the picture, we add the following to main.m

#import "ExceptionsBridge.h" // this goes immediately above the main() method

And,

exceptionTest(); // make this the first thing the main() method does

Note, if you are following along at home, remove any code added to the main() method in the previous article.

OK, so that is all the code. To recap, here’s what we did:

C++ side:

  • defined some custom C++ exception types derived from the standard lib exception base class
  • created a simple C++ class with a static method that throws and catches the custom exception types
  • logged output using the standard iostream classes
  • wrapped all this in a C function exported to be visible to the Objective C side

Objective C side:

  • imported the C wrapper function
  • invoked the C wrapper function

When this is built and run, we see the following on the console:

MyException1 was thrown
MyException2 was thrown
MyException3 was thrown
BadException was thrown

This is completely as expected, each of our custom exception types was thrown and caught. This is good news, it means that, at least in simple tests such as these, C++ support on iPhone is shaping up to be pretty nice: in part 1 we saw that global constructors are supported and here in part 2 we see that exception handling is supported. Coming up in part 3 is RTTI support.

  1. Great headstart, i’m looking forward to your next article about objective c / c++ interfacing.

    eg is it possible to call objectice c messages from c++ methods

  2. Anon, you can, but you still use the ObjC syntax. ObjC++ is basically C++ with the Objective stuff tacked on (in the same way ObjC is C with the Obj stuff tacked on). You can send messages or call methods anywhere, you just can’t intermingle the OO paradigms.

Comments are closed.