3. Mobile to C++ with Djinni

In this instalment of our React Native with C++ series, we learn how to use Djinni to generate a bridge from our Native code to C++

Rudi Yardley
4 min readJan 6, 2019

Mobile development is inherently a multi-lingual enterprise. Usually this means writing the same functionality in multiple languages which is a bad practice. In this series I want to explore an interesting technique for simplifying our codebase by utilising the power of C++ to achieve more maintainable cross platform development.

Other articles in this series:

  1. Why React Native needs C++
  2. Talking like a React Native
  3. Mobile to C++ with Djinni
  4. Connect React Native to C++
Photo by Dino Olivieri

So what about C++? Let’s groove with Djinni

So in our last instalment we setup basic communication between React Native and native code. In this article I want to cover how to set up our bridging code in order to communicate with C++.

Djinni is a great solution for sharing C++ code between mobile platforms. This bit is a little more involved but once you have it set up it is not too hard to work with.

Install Djinni

First, let’s install Djinni directly from their github. Djinni is the tool that is going to generate all our bridging code for us so we can maintain this interface over time by regenerating code.

yarn add --dev dropbox/djinni

Dropbox are not providing any official ‘releases’ of Djinni. I have been installing directly off the master branch and things have been working for me however you may want to use a commit hash for a big project.

yarn add --dev dropbox/djinni#51bf14f228579a78bc979f0e57c6849a708ed8aa

Create Djinni file

We now need to create an interface definition that describes our C++ interface we would like to use in our Native modules.

Create a file at ./helloworld.djinni with our interface definition in it:

hello_world = interface +c {
static create(): hello_world;
get_hello_world(): string;
}

This will expose a class from C++ that has a get_hello_world() method as well as a static create() method for simplifying object creation. For more information about Djinni and it’s IDL consult their documentation.

Create a run script

Djinni needs quite a bit of configuration so to do this easily we can create a run file in bash. I have called it ./run_djinni.sh.

./run_djinni.sh

Be sure to give this file executable permissions.

chmod +x ./run_djinni.sh

Time to run it.

./run_djinni.sh

Grab a twisty puzzle and a cup of joe as this will take ages the first time it runs as it must download all of Djinni’s Scala dependencies. Don’t think it is dead and stop it in the middle the way I did the first time I tried it.

Once this has completed you should find the following files created for you:

djinni/
├── cpp
│ └── hello_world.hpp
├── java
│ └── com
│ └── cppreactnative
│ └── helloworld
│ └── HelloWorld.java
├── jni
│ ├── NativeHelloWorld.cpp
│ └── NativeHelloWorld.hpp
└── objc
├── HWHelloWorld+Private.h
├── HWHelloWorld+Private.mm
└── HWHelloWorld.h

Let’s explore what Djinni has output.

Files for both iOS and Android

  • hello_world.hpp
    This file is the header file your C++ implementation that links everything together. Your implementation can extend from it. It defines the interface of your C++ module located by shared pointer reference. This is used by the Djinni bridging modules both through JNI and Objective C++.

Files for Android

  • HelloWorld.java
    This sets up a proxy class that is mapped to our C++ JNI bridge. This class has a similar interface to our C++ implementation we will write. We can use this proxy class as an entry point into C++ land.
  • NativeHelloWorld.hpp
    NativeHelloWorld.cpp
    This is JNI. JNI maps methods using convention to specific Java classes. They are usually complex and arduous to write and are held together by sticky tape. This code uses a bunch Djinni helper classes to marshal data and handle errors. The fact that Djinni autogenerates this code is its real value.

Files for iOS

  • HWHelloWorld.h
    HWHelloWorld+Private.h
    HWHelloWorld+Private.mm
    The HWHelloWorld+Private.mm Objective-C++ class utilises a shared pointer to reference the C++ implementation we will write. It uses a bunch of Djinni helper libs to marshal data and ensure errors are reported correctly between the world of Objective-C and C++.

Create a C++ class to implement our interface

We now need to create our core C++ entry point. For now let’s just make it a simple class with a method that returns a greeting string.

First let’s write a header file that includes the hello_world.hpp header that Djinni generated and then extend from the class that gives us.

src/cpp/hello_world_impl.hpp

Now let’s create the actual implementation. For now let’s simply return a string from the get_hello_world() method:

src/cpp/hello_world_impl.cpp

Our bridging code is now setup!

So far in this instalment we have used Djinni to generate complex bridging code that allows us to interface with Objective-C and C++ as well as Java and C++. We have also created a basic HelloWorld implementation in C++ to serve as our C++ backend for our React Native code. In our next and final instalment we look at how to connect our Djinni bridging code to C++ and React Native in both iOS and Android.

You can find the code associated with this article on my github.

Other articles in this series:

  1. Why React Native needs C++
  2. Talking like a React Native
  3. Mobile to C++ with Djinni
  4. Connect React Native to C++

This article is a living document and I am constantly learning please reach out to me if you want to contribute or see anything inaccurate here.

You can follow Rudi Yardley on Twitter as @rudiyardley or on Github as @ryardley

--

--

Rudi Yardley

Rudi Yardley is an independent senior full-stack software engineer and JavaScript/TypeScript/React specialist with over 19 years experience in industry.