CrossPlatCpp:适用于AndroidiOS的跨平台C ++示例应用程序

  • i4_718444
  • 3.4MB
  • zip
  • 0
  • VIP专享
  • 0
  • 2022-04-24 12:31
CrossPlatCpp 适用于Android / iOS的跨平台C ++示例应用程序
# 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 and video from ## 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 declarations: 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 rel='nofollow' onclick='return false;'>; # 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 | | | 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 (+) | | 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: 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 / 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 files for Objective-C / C++ are 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] | | Interface | my\_interface.hpp | my\_interface.cpp (+) | DBMyInterface.h | DBMyInterface+Private.h | | | | | | | (+) 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