Channels ▼


Interoperating Between C++ and Objective-C

This article is the first in a series that discusses low-level details of interoperability between C, Objective-C, C++, and Objective-C++. Future installments will appear under the author's name on her new blog at Dr. Dobb's. Ed.

The example I present below, as well as all other solutions in this series, were tested on XCode 4.6.2 on the Apple LLVM 4.2 (Clang) and LLVM GCC 4.2 compilers and also on the latest XCode 5. XCode 5.0 does not contain the GCC compiler anymore, so the samples were checked only on its Apple LLVM 5.0 (Clang). When not specified otherwise, the results are the same for the latest Clang.

Calling a C++ Class Constructor with Parameters from Objective-C Code

Suppose you have a C++ class, and it has a constructor with parameters:

class CppClass {
    CppClass(int arg1, const std::string& arg2): _arg1(arg1), _arg2(arg2) { }

    // ...
    int _arg1;
    std::string _arg2;

And you have an Objective-C class, which contains the object of the previous C++ class as a member.

@interface ObjC: NSObject {
    CppClass _cppClass;

@implementation ObjC

- (id)init
    self = [super init];
    if ( self )
// What should be the syntax of call CppClass::CppClass(5, "hello") for _cppClass?
    return self;

No matter how you try to call it, you will receive a compilation error.

Solution One

Rename the source file of the Objective-C class from .m in .mm to turn it into Objective-C++ module, so you can call methods of the C++ object.

Just a few words about Objective-C++. Both GCC and Clang are able to compile source files in C++ and Objective-C. It is even possible to mix C++ and Objective-C code in one file. As the object models are different, there are some restrictions. For example, a C++ class cannot derive from an Objective-C class and vice versa. If a file has the extension ".mm"  it is considered by a compiler to be an Objective-C++ file.

In general, you cannot call a constructor with parameters for an object itself. You can only call the default constructor. There is a workaround for this limitation: Use a pointer to a C++ object instead of a C++ object. You could create the pointer using new in a method , init(), and free it in dealloc() in the Objective-C class using the delete:

@interface ObjC: NSObject {
    CppClass *_pCppClass;

- (id)init
    self = [super init];
    if ( self )
        _pCppClass = new CppClass(5, "hello");
    return self;

- (void)dealloc
    delete _pCppClass;
    [super dealloc];

This solves the problem and is the approach I recommend. There is another partial solution though, but I would not recommend using it.

Solution Two.

You can change the C ++-class as follows:

template <int X, const char Y[]>
class CPPClass
    int _x;
    const char *_string ;

template <int X, const char Y[]>
CPPClass<X, Y>::CPPClass()
 : _x(X)
 , _string(Y)

Then, the Objective-C class will become like this:

extern const char kHelloWorld[] = "hello world";

@interface ObjC : NSObject
    CPPClass<5, kHelloWorld> thing;

I don't like this approach because of its restrictions. Note that the template parameter int can be a literal, but the parameter const char [] must be declared as a variable with an external linkage (as required by Clang). Omitting the extern in the declaration yields the following compilation error: "Non-template argument refers to object 'kHelloWorld' that does not have external linkage."

The two solutions work on both Clang and GCC.

Anna Koneva is a software engineer from Moscow, Russia. Her areas of interest and work include programming languages, especially C++, C#, and Objective-C. She develops desktop applications for Windows and mobile applications for the iPhone and iPad.

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.



Another way I've done this is to wrap my C++ object in a smart pointer. If only the creating instance needs to use the created object, then use a unique_ptr. If you need to support shallow copying, then use a shared_ptr.

For a very long time, the Objective-C runtime has automatically called C++ ctors and dtors on instance variables. That means I can set up the smart pointer in init using the custom ctor for my C++ class, and the object will be cleaned up automatically after -dealloc without me needing to call delete. The rest of the ObjC++ code is not changed from your new/delete example.