<commit_before># Djinni

Djinni is a tool for generating cross-language type declarations and interface bindings. It's
designed to connect C++ with either Java or Objective-C.

We at Dropbox use Djinni to interface cross-platform C++ library code with platform-specific
Java and Objective-C on Android and iOS.

We announced Djinni at CppCon 2014. Access the slides from https://bit.ly/djinnitalk and video from https://www.youtube.com/watch?v=ZcBtF-JWJhM

## Main Features
- Generates parallel C++, Java and Objective-C type definitions from a single interface
  description file.
- Supports the intersection of the three core languages' primitive types, and user-defined
  enums, records, and interfaces.
- Generates interface code allowing bidirectional calls between C++ and Java (with JNI) or
  Objective-C (with Objective-C++).
- Can autogenerate comparator functions (equality, ordering) on data types.

## Getting Started

### Types
Djinni generates code based on interface definitions in an IDL file. An IDL file can contain
three kinds of declaration: enums, records, and interfaces.

* Enums become C++ enum classes, Java enums, or ObjC `NS_ENUM`s.
* Records are pure-data value objects.
* Interfaces are objects with defined methods to call (in C++, passed by `shared_ptr`). Djinni
  produces code allowing an interface implemented in C++ to be transparently used from ObjC or
  Java, and vice versa.

### IDL Files
Djinni's input is an interface description file. Here's an example:

    # Multi-line comments can be added here. This comment will be propagated
    # to each generated definition.
    my_enum = enum {
        option1;
        option2;
        option3;
    }

    my_record = record {
        id: i32;
        info: string;
        store: set<string>;
        hash: map<string, i32>;

        values: list<another_record>;

        # Comments can also be put here

        # Constants can be included
        const string_const: string = "Constants can be put here";
        const min_value: another_record = {
            key1 = 0,
            key2 = ""
        };
    }

    another_record = record {
        key1: i32;
        key2: string;
    } deriving (eq, ord)

    # This interface will be implemented in C++ and can be called from any language.
    my_cpp_interface = interface +c {
        method_returning_nothing(value: i32);
        method_returning_some_type(key: string): another_record;
        static get_version(): i32;

        # Interfaces can also have constants
        const version: i32 = 1;
    }

    # This interface will be implemented in Java and ObjC and can be called from C++.
    my_client_interface = interface +j +o {
        log_string(str: string): bool;
    }

Djinni files can also include each other. Adding the line:

    @import "relative/path/to/filename.djinni"

at the beginning of a file will simply include another file. Child file paths are
relative to the location of the file that contains the @import. Two different djinni files
cannot define the same type. `@import` behaves like `#include` with `#pragma once` in C++, or
like ObjC's `#import`: if a file is included multiple times through different paths, then it
will only be processed once.

### Generate Code
When the Djinni file(s) are ready, from the command line or a bash script you can run:

    src/run \
       --java-out JAVA_OUTPUT_FOLDER \
       --java-package com.example.jnigenpackage \
       --java-cpp-exception DbxException \ # Choose between a customized C++ exception in Java and java.lang.RuntimeException (the default).
       --ident-java-field mFooBar \ # Optional, this adds an "m" in front of Java field names
       \
       --cpp-out CPP_OUTPUT_FOLDER \
       \
       --jni-out JNI_OUTPUT_FOLDER \
       --ident-jni-class NativeFooBar \ # This adds a "Native" prefix to JNI class
       \
       --objc-out OBJC_OUTPUT_FOLDER \
       --objc-type-prefix DB \ # Apple suggests Objective-C classes have a prefix for each defined type.
       \
       --idl MY_PROJECT.djinni

Some other options are also available, such as `--cpp-namespace` that put generated C++ code into the namespace specified. For a list of all options, run
`src/run --help`

Sample generated code is in the `example/generated-src/` and `test-suite/generated-src/`
directories of this distribution.

Note that if a language's output folder is not specified, that language will not be generated.
For more information, run `run --help` to see all command line arguments available.

### Use Generated Code in Your Project

#### Java / JNI / C++ Project

##### Includes & Build target
The following headers / code will be generated for each defined type:

| Type      | C++ header             | C++ source                 | Java                | JNI header            | JNI source            |
|-----------|------------------------|----------------------------|---------------------|-----------------------|-----------------------|
| Enum      | my\_enum.hpp           |                            | MyEnum.java         | NativeMyEnum.hpp      | NativeMyEnum.cpp      |
| Record    | my\_record[\_base].hpp | my\_record[\_base].cpp (+) | MyRecord[Base].java | NativeMyRecord.hpp    | NativeMyRecord.cpp    |
| Interface | my\_interface.hpp      | my\_interface.cpp (+)      | MyInterface.java    | NativeMyInterface.hpp | NativeMyInterface.cpp |

(+) Generated only for types that contain constants.

Add all generated source files to your build target, as well as the contents of
`support-lib/java`.

##### Our JNI approach
JNI stands for Java Native Interface, an extension of the Java language to allow interop with
native (C/C++) code or libraries. Complete documentation on JNI is available at:
http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html

For each type, built-in (`list`, `string`, etc.) or user-defined, Djinni produces a translator
class with a `toJava` and `fromJava` function to translate back and forth.

Application code is responsible for the initial load of the JNI library. Add a static block
somewhere in your code:

    System.loadLibrary("YourLibraryName");
    // The name is specified in Android.mk / build.gradle / Makefile, depending on your build system.

When a native library is called, JNI calls a special function called `JNI_OnLoad`. If you use
Djinni for all JNI interface code, include `support_lib/jni/djinni_main.cpp`; if not,
you'll need to add calls to your own `JNI_OnLoad` and `JNI_OnUnload` functions. See
`support-lib/jni/djinni_main.cpp` for details.

#### Objective-C / C++ Project

##### Includes & Build Target
Generated file for Objective-C / C++ is as follows (assuming prefix is `DB`):

| Type           | C++ header             | C++ source                 | Objective-C header                         | Objective-C source                  |
|----------------|------------------------|----------------------------|--------------------------------------------|-------------------------------------|
| Enum           | my\_enum.hpp           |                            | ` public/`DBMyEnum.h                       | `private/`DBMyEnumTranslator.mm     |
|                |                        |                            | `private/`DBMyEnumTranslator+Private.h     |                                     |
| Record         | my\_record[\_base].hpp | my\_record[\_base].cpp (+) | ` public/`DBMyRecord[Base].h               | `private/`DBMyRecord[Base].mm       |
|                |                        |                            | `private/`DBMyRecord[Base]+Private.h       |                                     |
| Interface `+c` | my\_interface.hpp      | my\_interface.cpp (+)      | ` public/`DBMyInterface.h                  | `private/`DBMyInterfaceCppProxy.mm  |
|                |                        |                            | ` public/`DBMyInterfaceCppProxy.h          |                                     |
|                |                        |                            | `private/`DBMyInterfaceCppProxy+Private.h  |                                     |
| Interface `+o` | my\_interface.hpp      | my\_interface.cpp (+)      | ` public/`DBMyInterface.h                  | `private/`DBMyInterfaceObjcProxy.mm |
|                |                        |                            | `private/`DBMyInterfaceObjcProxy+Private.h |                                     |

(+) Generated only for types that contain constants.

The folders `public` and `private` correspond to the options `--objc-out` and `--objc-private-out`
respecitvely, allowing you to isolate implementation headers and sources from the public files
exposed to Objective-C clients.

Add all generated files to your build target, as well as the contents of `support-lib/objc`.
Note that `+Private` headers can only be used with ObjC++ source (other headers are pure ObjC).

## Details of Generated Types
### Enum
Enums are translated to C++ `enum class`es with underlying type `int`, ObjC `NS_ENUM`s with
underlying type `NSInteger`, and Java enums.

### Record
Records are data objects. In C++, records contain all their elements by value, including other
records (so a record cannot contain itself).

#### Data type<commit_msg>Adjusted README to reflect the new file structure in the Objective-C generator<commit_after># Djinni

Djinni is a tool for generating cross-language type declarations and interface bindings. It's
designed to connect C++ with either Java or Objective-C.

We at Dropbox use Djinni to interface cross-platform C++ library code with platform-specific
Java and Objective-C on Android and iOS.

We announced Djinni at CppCon 2014. Access the slides from https://bit.ly/djinnitalk and video from https://www.youtube.com/watch?v=ZcBtF-JWJhM

## Main Features
- Generates parallel C++, Java and Objective-C type definitions from a single interface
  description file.
- Supports the intersection of the three core languages' primitive types, and user-defined
  enums, records, and interfaces.
- Generates interface code allowing bidirectional calls between C++ and Java (with JNI) or
  Objective-C (with Objective-C++).
- Can autogenerate comparator functions (equality, ordering) on data types.

## Getting Started

### Types
Djinni generates code based on interface definitions in an IDL file. An IDL file can contain
three kinds of declaration: enums, records, and interfaces.

* Enums become C++ enum classes, Java enums, or ObjC `NS_ENUM`s.
* Records are pure-data value objects.
* Interfaces are objects with defined methods to call (in C++, passed by `shared_ptr`). Djinni
  produces code allowing an interface implemented in C++ to be transparently used from ObjC or
  Java, and vice versa.

### IDL Files
Djinni's input is an interface description file. Here's an example:

    # Multi-line comments can be added here. This comment will be propagated
    # to each generated definition.
    my_enum = enum {
        option1;
        option2;
        option3;
    }

    my_record = record {
        id: i32;
        info: string;
        store: set<string>;
        hash: map<string, i32>;

        values: list<another_record>;

        # Comments can also be put here

        # Constants can be included
        const string_const: string = "Constants can be put here";
        const min_value: another_record = {
            key1 = 0,
            key2 = ""
        };
    }

    another_record = record {
        key1: i32;
        key2: string;
    } deriving (eq, ord)

    # This interface will be implemented in C++ and can be called from any language.
    my_cpp_interface = interface +c {
        method_returning_nothing(value: i32);
        method_returning_some_type(key: string): another_record;
        static get_version(): i32;

        # Interfaces can also have constants
        const version: i32 = 1;
    }

    # This interface will be implemented in Java and ObjC and can be called from C++.
    my_client_interface = interface +j +o {
        log_string(str: string): bool;
    }

Djinni files can also include each other. Adding the line:

    @import "relative/path/to/filename.djinni"

at the beginning of a file will simply include another file. Child file paths are
relative to the location of the file that contains the @import. Two different djinni files
cannot define the same type. `@import` behaves like `#include` with `#pragma once` in C++, or
like ObjC's `#import`: if a file is included multiple times through different paths, then it
will only be processed once.

### Generate Code
When the Djinni file(s) are ready, from the command line or a bash script you can run:

    src/run \
       --java-out JAVA_OUTPUT_FOLDER \
       --java-package com.example.jnigenpackage \
       --java-cpp-exception DbxException \ # Choose between a customized C++ exception in Java and java.lang.RuntimeException (the default).
       --ident-java-field mFooBar \ # Optional, this adds an "m" in front of Java field names
       \
       --cpp-out CPP_OUTPUT_FOLDER \
       \
       --jni-out JNI_OUTPUT_FOLDER \
       --ident-jni-class NativeFooBar \ # This adds a "Native" prefix to JNI class
       \
       --objc-out OBJC_OUTPUT_FOLDER \
       --objc-type-prefix DB \ # Apple suggests Objective-C classes have a prefix for each defined type.
       \
       --objcpp-out OBJC_OUTPUT_FOLDER \
       \
       --idl MY_PROJECT.djinni

Some other options are also available, such as `--cpp-namespace` that put generated C++ code into the namespace specified. For a list of all options, run
`src/run --help`

Sample generated code is in the `example/generated-src/` and `test-suite/generated-src/`
directories of this distribution.

Note that if a language's output folder is not specified, that language will not be generated.
For more information, run `run --help` to see all command line arguments available.

### Use Generated Code in Your Project

#### Java / JNI / C++ Project

##### Includes & Build target
The following headers / code will be generated for each defined type:

| Type      | C++ header             | C++ source                 | Java                | JNI header            | JNI source            |
|-----------|------------------------|----------------------------|---------------------|-----------------------|-----------------------|
| Enum      | my\_enum.hpp           |                            | MyEnum.java         | NativeMyEnum.hpp      | NativeMyEnum.cpp      |
| Record    | my\_record[\_base].hpp | my\_record[\_base].cpp (+) | MyRecord[Base].java | NativeMyRecord.hpp    | NativeMyRecord.cpp    |
| Interface | my\_interface.hpp      | my\_interface.cpp (+)      | MyInterface.java    | NativeMyInterface.hpp | NativeMyInterface.cpp |

(+) Generated only for types that contain constants.

Add all generated source files to your build target, as well as the contents of
`support-lib/java`.

##### Our JNI approach
JNI stands for Java Native Interface, an extension of the Java language to allow interop with
native (C/C++) code or libraries. Complete documentation on JNI is available at:
http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html

For each type, built-in (`list`, `string`, etc.) or user-defined, Djinni produces a translator
class with a `toJava` and `fromJava` function to translate back and forth.

Application code is responsible for the initial load of the JNI library. Add a static block
somewhere in your code:

    System.loadLibrary("YourLibraryName");
    // The name is specified in Android.mk / build.gradle / Makefile, depending on your build system.

When a native library is called, JNI calls a special function called `JNI_OnLoad`. If you use
Djinni for all JNI interface code, include `support_lib/jni/djinni_main.cpp`; if not,
you'll need to add calls to your own `JNI_OnLoad` and `JNI_OnUnload` functions. See
`support-lib/jni/djinni_main.cpp` for details.

#### Objective-C / C++ Project

##### Includes & Build Target
Generated file for Objective-C / C++ is as follows (assuming prefix is `DB`):

| Type      | C++ header             | C++ source                 | Objective-C files        | Objective-C++ files         |
|-----------|------------------------|----------------------------|--------------------------|-----------------------------|
| Enum      | my\_enum.hpp           |                            | DBMyEnum.h               |                             |
| Record    | my\_record[\_base].hpp | my\_record[\_base].cpp (+) | DBMyRecord[Base].h       | DBMyRecord[Base]+Private.h  |
|           |                        |                            | DBMyRecord[Base].mm (++) | DBMyRecord[Base]+Private.mm |
| Interface | my\_interface.hpp      | my\_interface.cpp (+)      | DBMyInterface.h          | DBMyInterface+Private.h     |
|           |                        |                            |                          | DBMyInterface+Private.mm    |

(+) Generated only for types that contain constants.
(++) Generated only for types with derived operations and/or constants. These have `.mm` extensions to allow non-trivial constants.

Add all generated files to your build target, as well as the contents of `support-lib/objc`.
Note that `+Private` files can only be used with ObjC++ source (other headers are pure ObjC) and are not required by Objective-C users of your interface.

## Details of Generated Types
### Enum
Enums are translated to C++ `enum class`es with underlying type `int`, ObjC `NS_ENUM`s with
underlying type `NSInteger`, and Java enums.

### Record
Records are data objects. In C++, records contain all their elements by value, including other
records (so a record cannot contain itself).

#### Data type
{'fraction_non_alphanumeric': 0.11528256083102806, 'fraction_numerical': 0.0029356969457460624, 'mean_word_length': 2.251468428781204, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 35, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4563961', 'n_tokens_mistral': 4880, 'n_tokens_neox': 4625, 'n_words': 1864}