# Library wrapper for Android APIs
Part of [Android Game Development Kit](https://developer.android.com/games/agdk/overview).

The library wrapper is a command-line tool (CLI) that generates C-language
wrapper code for Android APIs which are written in Java. You can use this
code in native Android apps to call Java APIs without needing to manually
create a [Java Native Interface](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/), or JNI. This tool can simplify development
Android apps written primarily in C or C++.

The tool works by generating C code for the public symbols contained in
Java Archive (JAR) files you provide, or classes defined in the tool's
configuration file, or both. Code generated by the tool does not replace Java
APIs; instead, it acts as a bridge between your C code and Java. Your app still
requires the Java libraries you wrap to be included in your project.

## Download

[Download](https://dl.google.com/developers/android/agdk/library_wrapper_1.0.0-beta1.zip) the library wrapper archive and unpack its content to the directory
of your choice.
| **Note:** The library wrapper requires Java Runtime Environment (JRE).

## Syntax

The library wrapper tool has the following command line syntax:  

    java -jar lw.jar \
      [-i jar-file-to-be-wrapped] \
      [-o output-path] \
      [-c config-file] \
      [-fa allow-list-file] \
      [-fb block-list-file] \
      [--skip_deprecated_symbols]

|        **Parameter**        |                                                                                    **Description**                                                                                     |
|-----------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `-i jar-file-to-be-wrapped` | JAR file to generate C wrapper code. Multiple JARs may be specified, for example: `-i first_library.jar -i second_library.jar...`                                                      |
| `-o output-path`            | File system location for the generated code.                                                                                                                                           |
| `-c config-file`            | File system path to the library wrapper configuration file. For details, see the [Configuration section](https://developer.android.com/games/develop/custom/wrapper#config).           |
| `-fa allow-list-file`       | A path to a filter file where you can specify symbols for the tool to wrap. For details, see the [Filter](https://developer.android.com/games/develop/custom/wrapper#filters) section. |
| `-fb block-list-file`       | A path to a filter file containing symbols excluded from wrapping. For details, see the [Filter](https://developer.android.com/games/develop/custom/wrapper#filters) section.          |
| `--skip_deprecated_symbols` | Instructs the wrapper tool to skip [@Deprecated](https://developer.android.com/reference/java/lang/Deprecated) symbols.                                                                |

## Wrapper configuration file

The library wrapper configuration is a JSON file allowing you to control the
code generation process. The file uses the following structure.
**Note:** The following example configuration contains comments which are not valid JSON. Also, the values specified should only be used as examples. To use this configuration in your project, remove the comments and replace the example values with your own.  

    {
      // An array of type-specific configs. A type config is useful when a user wants to map
      // a Java type to a manually defined C type without generating the code. For example, when a developer
      // has their own implementation of the "java.lang.String" class, they can tell the generator to use it
      // instead of generating it.
      "type_configs": [
        {
          // [Required] Name of a fully qualified Java type.
          "java_type": "java.lang.String",
          // The C type that the java_type will be mapped to.
          "map_to": "MyOwnStringImplementation",
          // A header file that contains the declaration of the "map_to" type.
          "source_of_definition": "my_wrappers/my_own_string_implementation.h",
          // Controls if a value should be passed by pointer or value.
          "pass_by_value": false
        }
      ],
      // An array of package-specific configs.
      "package_configs": [
        {
          // [Required] A name of a Java package that this section regards. A wildchar * can be used at the
          // end of the package name to apply this config to all packages whose name starts with this value.
          "package_name": "androidx.core.app*",
          // A subdirectory relative to the root directory where the generated code will be located.
          "sub_directory": "androidx_generated/",
          // If true, the generated file structure reflects the package name. For example, files generated
          // for the package com.google.tools will be placed in the directory com/google/tools/.
          "file_location_by_package_name": true,
          // A prefix added to all class names from this package.
          "code_prefix": "Gen",
          // A prefix added to all generated file names from this package.
          "file_prefix": = "gen_"
        }
      ],
      // An array of manually defined classes for wrapping. Defining classes manually is useful when a
      // jar file with desired classes are not available or a user needs to wrap just a small part of an SDK.
      "custom_classes": [
        {
          // [Required] A fully-qualified Java class name. To define inner class, use symbol "$", for example
          // "class com.example.OuterClass$InnerClass".
          "class_name": "class java.util.ArrayList<T>",
          // List of methods.
          "methods": [
            "ArrayList()", // Example of a constructor.
            "boolean add(T e)", // Example of a method that takes a generic parameter.
            "T get(int index)", // Example of a method that returns a generic parameter.
            "int size()" // Example of parameterless method.
          ]
        },
      ]
    }

## Filter files

It may be useful to exclude some symbols from the JAR files you plan to wrap. You
can specify a filter file in your configuration to exclude symbols. A filter file
is a simple text file where each line defines a symbol to wrap. Filter files use
the following syntax:  

    java-symbol-name java-jni-type-signature

The following is an example filter file:  

    # Class filter
    java.util.ArrayList Ljava.util.ArrayList;

    # Method filter
    java.util.ArrayList.lastIndexOf (Ljava.lang.Object;)I

    # Field filter
    android.view.KeyEvent.KEYCODE_ENTER I

| **Note:** See [JNL Types and Data Structures](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html) to learn more about JNI type signatures.

You provide the [configuration](https://developer.android.com/games/develop/custom/wrapper#syntax) a filter file specifying symbols that
are allowed using the `-fa` parameter, and blocked symbols using the `-fb`
parameter. Both parameters can be used simultaneously. If both filters are
provided, a symbol will be wrapped when it is defined in the allow filter file
and is not present on the block filter file.

## Example scenario

Assume that you need to wrap the JAR file `ChatLibrary.jar` containing the
following class:  

    public class ChatManager {
      public static void sendMessage(int userId, String message) {...}
    }

Your C project requires you to generate a native wrapper for this JAR, enabling
your native Android app to call it during runtime. Generate this code using the
library wrapper with the following command:  

    java -jar lw.jar -i ChatLibrary.jar -o ./generated_code/

The preceding command generates C source code to the directory
`./generated_code`. The generated file `chat_manager.h` contains code similar to
the following, enabling you to call the library in your project:  

    #include "java/lang/string.h"

    typedef struct ChatManager_ ChatManager;
    void ChatManager_sendMessage(int32_t user_id, String* message);

For an in-depth example scenario, see the [Library wrapper guide](https://developer.android.com/games/develop/custom/wrapper-guide).

## Tool details

The following sections provide detailed information of the library wrapper's
functionality.

### Output directory structure

All C source and header files are located in subdirectories that reflect the
package name of the wrapped Java class. For example, wrapper code for the
specified JAR `java.lang.Integer` is generated to the directory
`./java/lang/integer.[h/cc]`.

You can control this output behavior using the tool's
[configuration](https://developer.android.com/games/develop/custom/wrapper#config) file.
| **Note:** There are two intermediate directories in your generated base directory: `c` and `cpp`. The `cpp` directory contains the temporary C++ wrappers.

### Object lifecycle

Java objects are represented in the C code as opaque pointers, called wrappers.
A wrapper manages a JNI reference for a corresponding Java object. A wrapper can
be created in the following scenarios:

- By wrapping an existing JNI reference by calling the function *MyClass*`_wrapJniReference(jobject jobj)`. The function does not take the ownership of the provided reference, but creates its own global JNI reference.
- By creating a new object, which is equivalent to calling a constructor in Java: *MyClass*`_construct()`
- By returning a new wrapper from a function, for example: `Score* Leaderboard_getScore(Leaderboard* instance, String* leaderboard_name)`

You need to destroy all wrappers when they're no longer used. To do so, call the dedicated
`destroy()` function *MyClass* `_destroy(`*MyClass*`* instance)`.

Functions that return wrappers allocate a new memory for them for every call,
even if wrappers represent the same Java instance.

For example, when the Java method `Singleton.getInstance()` always returns the
same instance, the equivalent function on the C side will create a new instance
of a wrapper for the same Java instance:  

    Singleton* singleton_a = Singleton_getInsance();
    Singleton* singleton_b = Singleton_getInsance();

    // singleton_a and singleton_b are different pointers, even though they represent the same Java instance.

### Handle unreferenced classes

When a class can't be found in a provided JAR, the libarary wrapper creates a
basic implementation consisting of an opaque pointer and the following methods:

- `wrapJniReference()`
- `getJniReference()`
- `destroy()`

### Code generation details

When run, the library wrapper generates C code based on the public symbols in
the JAR file(s) you provide the tool. Generated C code may exhibit differences
from the wrapped Java code. For example, C does not support features like OOP,
generic types, method overloading, or other Java features.

The generated C code reflecting these situations may differ from the type of
code expected by C developers. The examples in the following sections provide
context on how the tool may generate C from Java code.
Note: In the code snippets, the following examples include C/C++ and Java code
snippets. These snippets are solely intended to demonstrate how the tool
generates code for the each given situation.

#### Classes

Classes are represented as [opaque pointers](https://en.wikipedia.org/wiki/Opaque_pointer) in C:  

### C/C++

    typedef struct MyClass_ MyClass;

### Java

    public class MyClass { ... }

Instances of opaque pointers are referenced as *wrappers* . The wrapper tool
generates additional support functions for each class. For the preceding example
class `MyClass`, the following functions are generated:  

    // Wraps a JNI reference with MyClass. The 'jobj' must represent MyClass on the Java side.
    MyClass* MyClass_wrapJniReference(jobject jobj);

    // Return JNI reference associated with the 'MyClass' pointer.
    jobject MyClass_getJniReference(const MyClass* object);

    // Destroys the object and releases underlying JNI reference.
    void MyClass_destroy(const MyClass* object);

#### Constructors

Classes with public or default constructors are represented using special
functions:  

### C/C++

    MyClass* MyClass_construct(String* data);

### Java

    public class MyClass {
      public MyClass(String data) { ... }
    }

#### Methods

Methods are represented as normal functions. The name of a function contains the
original class name. Functions that represent non-static instance methods have
as the first parameter a pointer to a structure representing a Java object, on
behalf of which the function is called. This approach is analogous to the `this`
pointer.
**Note:** Static methods don't have this parameter.  

### C/C++

    Result* MyClass_doAction(const MyClass* my_class_instance, int32_t action_id, String* data);
    int32_t MyClass_doAction(int32_t a, int32_t b);

### Java

    public class MyClass {
      public Result doAction(int actionId, String data) { ... }
      public static int doCalculations(int a, int b) { ... }
    }

#### Inner classes

Inner classes are represented closely to normal classes, except the name of the
corresponding C structure contains the chained names of outer classes:  

### C/C++

    typedef struct MyClass_InnerClass_ MyClass_InnerClass;

### Java

    public class MyClass {
      public class InnerClass {...}
    }

#### Inner class methods

Inner class methods are represented as follows:  

### C/C++

    bool MyClass_InnerClass_setValue(MyClass_InnerClass* my_class_inner_class_instance, int32_t value);

### Java

    public class MyClass {
      public class InnerClass {
        public boolean setValue(int value) { ... }
      }
    }

#### Generic types

The library wrapper does not directly wrap generic types. Instead, the tool
only generates wrappers for generic type instantiations.

For example, when a class `MyGeneric<T>` exists in an API, and there are two
instantiations of this class, such as `MyGeneric<Integer>` and
`MyGeneric<String>`, wrappers for those two instantiations are generated. This
means that you cannot create new instantiations of type `MyGeneric<T>` using
different type configurations. See the following example:  

### C/C++

    // result.h

    typedef struct Result_Integer_ Result_Integer;
    typedef struct Result_Float_ Result_Float;

    Integer* Result_Integer_getResult(const Result_Integer* instance);
    Float* Result_Float_getResult(const Result_Float* instance);

    // data_processor.h

    typedef struct DataProcessor_ DataProcessor;

    Result_Integer* DataProcessor_processIntegerData(const DataProcessor* instance);
    Result_Float* DataProcessor_processFloatData(constDataProcessor* instance);

### Java

    public class Result<T> {
      public T getResult();
    }

    public class DataProcessor {
      public Result<Integer> processIntegerData();
      public Result<Float> processFloatData();
    }

#### Implement interfaces

Implement a C interface by calling `implementInterface()` and providing a
callback function for each interface method. Only interfaces may be implemented
in this manner; classes and abstract classes are not supported. See the
following example:  

### C/C++

    // observer.h

    typedef struct Observer_ Observer;
    typedef void (*Observer_onAction1Callback)();
    typedef void (*Observer_onAction2Callback)(int32_t data);

    Observer* Observer_implementInterface(
    Observer_onAction1Callback observer_on_action1_callback,
    Observer_onAction2Callback observer_on_action2_callback);

### Java

    public interface Observer {
      void onAction1();
      void onAction2(int data);
    }

    public class Subject {
      public void registerObserver(Observer observer);
    }

Usage example:  

    void onAction1() {
      // Handle action 1
    }

    void onAction2(int32_t data) {
      // Handle action 2
    }

    Observer* observer = Observer_implementInterface(onAction1, onAction2);
    Subject_registerObserver(subject, observer);

## Limitations

The library wrapper tool is in beta. You may encounter the following
limitations:

#### Unsupported Java constructs

The library wrapper beta does not support the following constructs:

- Method overloading

  The C language doesn't allow declaring two functions with the same name. If
  the class uses method overloading, the generated C code won't compile. The
  workaround is to use only one method with a sufficient set of parameters.
  The remaining functions can be filtered out using [filters](https://developer.android.com/games/develop/custom/wrapper#filters). This
  also applies to constructors.
- Templated methods

- Fields other than `static final int` and `static final String`

- Arrays

#### Potential name collisions

Because of how Java classes are represented in C code, there may be name
conflicts in very rare cases. For example, a class `Foo<Bar>` and an inner
class `Bar` inside a `Foo` class are represented by the same symbol in C:
`typedef struct Foo_Bar_ Foo_Bar;`

## Support

If you find an issue with the library wrapper, please let us know.

|                                  Browse bugs                                   |                                 File a bug                                  |
|--------------------------------------------------------------------------------|-----------------------------------------------------------------------------|
| [Engineering](http://issuetracker.google.com/issues?q=componentid:778598%2B)   | [*bug_report*](https://issuetracker.google.com/issues/new?component=778598) |
| [Documentation](http://issuetracker.google.com/issues?q=componentid:778285%2B) | [*bug_report*](https://issuetracker.google.com/issues/new?component=778285) |

*** ** * ** ***