Commit 9d1d6404 authored by Miro Knejp's avatar Miro Knejp

Refactored JNI code generation

- Renamed toJava/fromJava methods to fromCpp/toCpp for consistency among language generators
- fromCpp methods return LocaLRef<JniType> instead of JniType for improved exception safety
- Merged primitive converters into a single header file and fixed for LocalRef<T> changes
- Avoiding local temporaries where feasible
- Consistent call signatures
- Proper support for templated JNI types
parent 82ca9318
......@@ -2,24 +2,26 @@
// This file generated by Djinni from example.djinni
#include "NativeItemList.hpp" // my header
#include "HList.hpp"
#include "HString.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativeItemList::toJava(JNIEnv* jniEnv, ::textsort::ItemList c) {
djinni::LocalRef<jobject> j_items(jniEnv, ::djinni::HList<::djinni::HString>::toJava(jniEnv, c.items));
const auto & data = djinni::JniClass<::djinni_generated::NativeItemList>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_items.get());
djinni::jniExceptionCheck(jniEnv);
NativeItemList::NativeItemList() = default;
NativeItemList::~NativeItemList() = default;
auto NativeItemList::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeItemList>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::List<::djinni::String>::fromCpp(jniEnv, c.items).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::textsort::ItemList NativeItemList::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeItemList::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeItemList>::get();
return ::textsort::ItemList(
::djinni::HList<::djinni::HString>::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mItems)).get()));
const auto& data = ::djinni::JniClass<NativeItemList>::get();
return {::djinni::List<::djinni::String>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mItems))};
}
} // namespace djinni_generated
......@@ -13,16 +13,20 @@ public:
using CppType = ::textsort::ItemList;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::textsort::ItemList);
static ::textsort::ItemList fromJava(JNIEnv*, jobject);
using Boxed = NativeItemList;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/textsort/ItemList") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/ArrayList;)V") };
const jfieldID field_mItems { djinni::jniGetFieldID(clazz.get(), "mItems", "Ljava/util/ArrayList;") };
~NativeItemList();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeItemList() {}
friend class djinni::JniClass<::djinni_generated::NativeItemList>;
NativeItemList();
friend ::djinni::JniClass<NativeItemList>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/textsort/ItemList") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/ArrayList;)V") };
const jfieldID field_mItems { ::djinni::jniGetFieldID(clazz.get(), "mItems", "Ljava/util/ArrayList;") };
};
} // namespace djinni_generated
......@@ -9,9 +9,10 @@
namespace djinni_generated {
NativeSortItems::NativeSortItems() : djinni::JniInterface<::textsort::SortItems, NativeSortItems>("com/dropbox/textsort/SortItems$CppProxy") {}
NativeSortItems::NativeSortItems() : ::djinni::JniInterface<::textsort::SortItems, NativeSortItems>("com/dropbox/textsort/SortItems$CppProxy") {}
NativeSortItems::~NativeSortItems() = default;
using namespace ::djinni_generated;
CJNIEXPORT void JNICALL Java_com_dropbox_textsort_SortItems_00024CppProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef)
{
......@@ -25,11 +26,9 @@ CJNIEXPORT void JNICALL Java_com_dropbox_textsort_SortItems_00024CppProxy_native
{
try {
DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef);
const std::shared_ptr<::textsort::SortItems> & ref = djinni::CppProxyHandle<::textsort::SortItems>::get(nativeRef);
::textsort::sort_order c_order = NativeSortOrder::fromJava(jniEnv, j_order);
::textsort::ItemList c_items = NativeItemList::fromJava(jniEnv, j_items);
ref->sort(c_order, c_items);
const auto& ref = ::djinni::CppProxyHandle<::textsort::SortItems>::get(nativeRef);
ref->sort(::djinni_generated::NativeSortOrder::toCpp(jniEnv, j_order),
::djinni_generated::NativeItemList::toCpp(jniEnv, j_items));
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
}
......@@ -37,11 +36,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_textsort_SortItems_createWithListene
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::shared_ptr<::textsort::TextboxListener> c_listener = NativeTextboxListener::fromJava(jniEnv, j_listener);
std::shared_ptr<::textsort::SortItems> cr = ::textsort::SortItems::create_with_listener(c_listener);
return NativeSortItems::toJava(jniEnv, cr);
auto r = ::textsort::SortItems::create_with_listener(::djinni_generated::NativeTextboxListener::toCpp(jniEnv, j_listener));
return ::djinni_generated::NativeSortItems::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......
......@@ -8,18 +8,23 @@
namespace djinni_generated {
class NativeSortItems final : djinni::JniInterface<::textsort::SortItems, NativeSortItems> {
class NativeSortItems final : ::djinni::JniInterface<::textsort::SortItems, NativeSortItems> {
public:
using CppType = std::shared_ptr<::textsort::SortItems>;
using JniType = jobject;
static jobject toJava(JNIEnv* jniEnv, std::shared_ptr<::textsort::SortItems> c) { return djinni::JniClass<::djinni_generated::NativeSortItems>::get()._toJava(jniEnv, c); }
static std::shared_ptr<::textsort::SortItems> fromJava(JNIEnv* jniEnv, jobject j) { return djinni::JniClass<::djinni_generated::NativeSortItems>::get()._fromJava(jniEnv, j); }
using Boxed = NativeSortItems;
~NativeSortItems();
static CppType toCpp(JNIEnv* jniEnv, JniType j) { return ::djinni::JniClass<NativeSortItems>::get()._fromJava(jniEnv, j); }
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) { return {jniEnv, ::djinni::JniClass<NativeSortItems>::get()._toJava(jniEnv, c)}; }
private:
NativeSortItems();
friend class djinni::JniClass<::djinni_generated::NativeSortItems>;
friend ::djinni::JniClass<NativeSortItems>;
friend ::djinni::JniInterface<::textsort::SortItems, NativeSortItems>;
};
} // namespace djinni_generated
......@@ -8,17 +8,19 @@
namespace djinni_generated {
class NativeSortOrder final : djinni::JniEnum {
class NativeSortOrder final : ::djinni::JniEnum {
public:
using CppType = ::textsort::sort_order;
using JniType = jobject;
static jobject toJava(JNIEnv* jniEnv, ::textsort::sort_order c) { return djinni::JniClass<NativeSortOrder>::get().create(jniEnv, static_cast<int>(c)).release(); }
static ::textsort::sort_order fromJava(JNIEnv* jniEnv, jobject j) { return static_cast<::textsort::sort_order>(djinni::JniClass<NativeSortOrder>::get().ordinal(jniEnv, j)); }
using Boxed = NativeSortOrder;
static CppType toCpp(JNIEnv* jniEnv, JniType j) { return static_cast<CppType>(::djinni::JniClass<NativeSortOrder>::get().ordinal(jniEnv, j)); }
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, CppType c) { return ::djinni::JniClass<NativeSortOrder>::get().create(jniEnv, static_cast<jint>(c)); }
private:
NativeSortOrder() : JniEnum("com/dropbox/textsort/SortOrder") {}
friend class djinni::JniClass<NativeSortOrder>;
friend ::djinni::JniClass<NativeSortOrder>;
};
} // namespace djinni_generated
......@@ -6,17 +6,21 @@
namespace djinni_generated {
NativeTextboxListener::NativeTextboxListener() : djinni::JniInterface<::textsort::TextboxListener, NativeTextboxListener>() {}
NativeTextboxListener::JavaProxy::JavaProxy(jobject obj) : JavaProxyCacheEntry(obj) {}
void NativeTextboxListener::JavaProxy::JavaProxy::update(const ::textsort::ItemList & c_items) {
JNIEnv * const jniEnv = djinni::jniGetThreadEnv();
djinni::JniLocalScope jscope(jniEnv, 10);
djinni::LocalRef<jobject> j_items(jniEnv, NativeItemList::toJava(jniEnv, c_items));
const auto & data = djinni::JniClass<::djinni_generated::NativeTextboxListener>::get();
jniEnv->CallVoidMethod(getGlobalRef(), data.method_update, j_items.get());
djinni::jniExceptionCheck(jniEnv);
};
NativeTextboxListener::NativeTextboxListener() : ::djinni::JniInterface<::textsort::TextboxListener, NativeTextboxListener>() {}
NativeTextboxListener::~NativeTextboxListener() = default;
NativeTextboxListener::JavaProxy::JavaProxy(JniType j) : JavaProxyCacheEntry(j) { }
NativeTextboxListener::JavaProxy::~JavaProxy() = default;
void NativeTextboxListener::JavaProxy::update(const ::textsort::ItemList & items) {
auto jniEnv = ::djinni::jniGetThreadEnv();
::djinni::JniLocalScope jscope(jniEnv, 10);
const auto& data = ::djinni::JniClass<::djinni_generated::NativeTextboxListener>::get();
jniEnv->CallVoidMethod(getGlobalRef(), data.method_update,
::djinni_generated::NativeItemList::fromCpp(jniEnv, items).get());
::djinni::jniExceptionCheck(jniEnv);
}
} // namespace djinni_generated
......@@ -8,31 +8,39 @@
namespace djinni_generated {
class NativeTextboxListener final : djinni::JniInterface<::textsort::TextboxListener, NativeTextboxListener> {
class NativeTextboxListener final : ::djinni::JniInterface<::textsort::TextboxListener, NativeTextboxListener> {
public:
using CppType = std::shared_ptr<::textsort::TextboxListener>;
using JniType = jobject;
static jobject toJava(JNIEnv* jniEnv, std::shared_ptr<::textsort::TextboxListener> c) { return djinni::JniClass<::djinni_generated::NativeTextboxListener>::get()._toJava(jniEnv, c); }
static std::shared_ptr<::textsort::TextboxListener> fromJava(JNIEnv* jniEnv, jobject j) { return djinni::JniClass<::djinni_generated::NativeTextboxListener>::get()._fromJava(jniEnv, j); }
using Boxed = NativeTextboxListener;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/textsort/TextboxListener") };
const jmethodID method_update { djinni::jniGetMethodID(clazz.get(), "update", "(Lcom/dropbox/textsort/ItemList;)V") };
~NativeTextboxListener();
class JavaProxy final : djinni::JavaProxyCacheEntry, public ::textsort::TextboxListener {
static CppType toCpp(JNIEnv* jniEnv, JniType j) { return ::djinni::JniClass<NativeTextboxListener>::get()._fromJava(jniEnv, j); }
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) { return {jniEnv, ::djinni::JniClass<NativeTextboxListener>::get()._toJava(jniEnv, c)}; }
private:
NativeTextboxListener();
friend ::djinni::JniClass<NativeTextboxListener>;
friend ::djinni::JniInterface<::textsort::TextboxListener, NativeTextboxListener>;
class JavaProxy final : ::djinni::JavaProxyCacheEntry, public ::textsort::TextboxListener
{
public:
JavaProxy(jobject obj);
virtual void update(const ::textsort::ItemList & items) override;
JavaProxy(JniType j);
~JavaProxy();
void update(const ::textsort::ItemList & items) override;
private:
using djinni::JavaProxyCacheEntry::getGlobalRef;
friend class djinni::JniInterface<::textsort::TextboxListener, ::djinni_generated::NativeTextboxListener>;
friend class djinni::JavaProxyCache<JavaProxy>;
using ::djinni::JavaProxyCacheEntry::getGlobalRef;
friend ::djinni::JniInterface<::textsort::TextboxListener, ::djinni_generated::NativeTextboxListener>;
friend ::djinni::JavaProxyCache<JavaProxy>;
};
private:
NativeTextboxListener();
friend class djinni::JniClass<::djinni_generated::NativeTextboxListener>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/textsort/TextboxListener") };
const jmethodID method_update { ::djinni::jniGetMethodID(clazz.get(), "update", "(Lcom/dropbox/textsort/ItemList;)V") };
};
} // namespace djinni_generated
......@@ -49,7 +49,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
}
def find(m: Meta) = m match {
case o: MOpaque =>
jniCpp.add("#include " + q(spec.jniBaseLibIncludePrefix + jniBaseLibFileIdentStyle(o.idlName) + ".hpp"))
jniCpp.add("#include " + q(spec.jniBaseLibIncludePrefix + "Marshal.hpp"))
case d: MDef =>
jniCpp.add("#include " + q(spec.jniIncludePrefix + spec.jniFileIdentStyle(d.name) + "." + spec.cppHeaderExt))
case p: MParam =>
......@@ -62,18 +62,20 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
val cppSelf = cppMarshal.fqTypename(ident, e)
writeJniHppFile(ident, origin, Iterable.concat(refs.jniHpp, refs.jniCpp), Nil, w => {
w.w(s"class $jniHelper final : djinni::JniEnum").bracedSemi {
w.w(s"class $jniHelper final : ::djinni::JniEnum").bracedSemi {
w.wlOutdent("public:")
w.wl(s"using CppType = $cppSelf;")
w.wl(s"using JniType = jobject;")
w.wl
w.wl(s"static jobject toJava(JNIEnv* jniEnv, $cppSelf c) { return djinni::JniClass<$jniHelper>::get().create(jniEnv, static_cast<int>(c)).release(); }")
w.wl(s"static $cppSelf fromJava(JNIEnv* jniEnv, jobject j) { return static_cast<$cppSelf>(djinni::JniClass<$jniHelper>::get().ordinal(jniEnv, j)); }")
w.wl(s"using Boxed = $jniHelper;")
w.wl
w.wl(s"static CppType toCpp(JNIEnv* jniEnv, JniType j) { return static_cast<CppType>(::djinni::JniClass<$jniHelper>::get().ordinal(jniEnv, j)); }")
w.wl(s"static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, CppType c) { return ::djinni::JniClass<$jniHelper>::get().create(jniEnv, static_cast<jint>(c)); }")
w.wl
w.wlOutdent("private:")
val classLookup = q(jniMarshal.undecoratedTypename(ident, e))
w.wl(s"$jniHelper() : JniEnum($classLookup) {}")
w.wl(s"friend class djinni::JniClass<$jniHelper>;")
w.wl(s"friend ::djinni::JniClass<$jniHelper>;")
}
})
}
......@@ -84,7 +86,6 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
val jniHelper = jniMarshal.helperClass(ident)
val cppSelf = cppMarshal.fqTypename(ident, r) + cppTypeArgs(params)
val fqJniHelper = jniMarshal.fqHelperClass(ident)
def writeJniPrototype(w: IndentWriter) {
writeJniTypeParams(w, params)
......@@ -93,78 +94,77 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
w.wl(s"using CppType = $cppSelf;")
w.wl(s"using JniType = jobject;")
w.wl
w.wl(s"static jobject toJava(JNIEnv*, $cppSelf);")
w.wl(s"static $cppSelf fromJava(JNIEnv*, jobject);")
w.wl(s"using Boxed = $jniHelper;")
w.wl
w.wl(s"~$jniHelper();")
w.wl
w.wl(s"static CppType toCpp(JNIEnv* jniEnv, JniType j);")
w.wl(s"static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);")
w.wl
w.wlOutdent("private:")
w.wl(s"$jniHelper();")
w.wl(s"friend ::djinni::JniClass<$jniHelper>;")
w.wl
val classLookup = q(jniMarshal.undecoratedTypename(ident, r))
w.wl(s"const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass($classLookup) };")
val constructorSig = q(toJavaMethodSig(spec.javaPackage, r.fields, None))
w.wl(s"const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), ${q("<init>")}, $constructorSig) };")
w.wl(s"const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass($classLookup) };")
val constructorSig = q(jniMarshal.javaMethodSignature(r.fields, None))
w.wl(s"const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), ${q("<init>")}, $constructorSig) };")
for (f <- r.fields) {
val javaFieldName = idJava.field(f.ident)
val javaSig = q(jniMarshal.fqTypename(f.ty))
w.wl(s"const jfieldID field_$javaFieldName { djinni::jniGetFieldID(clazz.get(), ${q(javaFieldName)}, $javaSig) };")
w.wl(s"const jfieldID field_$javaFieldName { ::djinni::jniGetFieldID(clazz.get(), ${q(javaFieldName)}, $javaSig) };")
}
w.wl
w.wlOutdent("private:")
w.wl(s"$jniHelper() {}")
w.wl(s"friend class djinni::JniClass<$fqJniHelper>;")
}
}
def writeJniBody(w: IndentWriter) {
val jniHelperWithParams = jniHelper + typeParamsSignature(params)
// Defining ctor/dtor in the cpp file reduces build times
writeJniTypeParams(w, params)
w.wl(s"$jniHelperWithParams::$jniHelper() = default;")
w.wl
writeJniTypeParams(w, params)
w.wl(s"$jniHelperWithParams::~$jniHelper() = default;")
w.wl
val dataVar = if (r.fields.nonEmpty) " c" else ""
w.w(s"jobject $jniHelper::toJava(JNIEnv* jniEnv, $cppSelf$dataVar)").braced{
writeJniTypeParams(w, params)
w.w(s"auto $jniHelperWithParams::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType>").braced{
//w.wl(s"::${spec.jniNamespace}::JniLocalScope jscope(jniEnv, 10);")
val jniArgs = mutable.ListBuffer[String]()
for (f <- r.fields) {
val jniLocal = "j_" + idCpp.local(f.ident)
val cppFieldName = idCpp.field(f.ident)
val jniHelperClass = toJniHelperClass(f.ty)
val jniLocalRead = storeLocal(w, jniLocal, f.ty, s"$jniHelperClass::toJava(jniEnv, c.$cppFieldName)")
jniArgs.append(jniLocalRead)
if(r.fields.isEmpty) w.wl("(void)c; // Suppress warnings in release builds for empty records")
w.wl(s"const auto& data = ::djinni::JniClass<$jniHelper>::get();")
val call = "auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject("
w.w(call + "data.clazz.get(), data.jconstructor")
if(!r.fields.isEmpty) {
w.wl(",")
writeAlignedCall(w, " " * call.length(), r.fields, ")}", f => {
val name = idCpp.field(f.ident)
val get = if(jniMarshal.isJavaHeapObject(f.ty)) ".get()" else ""
jniMarshal.fromCpp(f.ty, s"c.$name") + get
})
}
w.wl(s"const auto & data = djinni::JniClass<$fqJniHelper>::get();")
val argList = jniArgs.map(", " + _).mkString("")
w.wl(s"jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor$argList);")
w.wl(s"djinni::jniExceptionCheck(jniEnv);")
else
w.w(")}")
w.wl(";")
w.wl(s"::djinni::jniExceptionCheck(jniEnv);")
w.wl(s"return r;")
}
w.wl
writeJniTypeParams(w, params)
if (r.fields.nonEmpty) {
w.w(s"$cppSelf $jniHelper::fromJava(JNIEnv* jniEnv, jobject j)").braced {
//w.wl(s"::${spec.jniNamespace}::JniLocalScope jscope(jniEnv, 10);")
w.wl(s"assert(j != nullptr);")
w.wl(s"const auto & data = djinni::JniClass<$fqJniHelper>::get();")
w.wl(s"return $cppSelf(").nested {
val skipFirst = SkipFirst()
for (f <- r.fields) {
skipFirst { w.wl(",") }
val jniHelperClass = toJniHelperClass(f.ty)
val fieldId = "data.field_" + idJava.field(f.ident)
var jniFieldAccess = toJniCall(f.ty, (jt: String) => s"jniEnv->Get${jt}Field(j, $fieldId)")
if (isJavaHeapObject(f.ty)) {
val jniTy = toJniType(f.ty)
jniFieldAccess = s"djinni::LocalRef<$jniTy>(jniEnv, $jniFieldAccess).get()"
}
w.w(s"$jniHelperClass::fromJava(jniEnv, $jniFieldAccess)")
}
w.wl(");")
}
}
} else {
w.w(s"$cppSelf $jniHelper::fromJava(JNIEnv*, jobject j)").braced {
w.wl("assert(j != nullptr);")
w.wl("(void) j; // Suppress unused error in release build")
w.wl(s"return $cppSelf();")
}
w.w(s"auto $jniHelperWithParams::toCpp(JNIEnv* jniEnv, JniType j) -> CppType").braced {
//w.wl(s"::${spec.jniNamespace}::JniLocalScope jscope(jniEnv, 10);")
w.wl(s"assert(j != nullptr);")
if(r.fields.isEmpty)
w.wl("(void)j; // Suppress warnings in release builds for empty records")
else
w.wl(s"const auto& data = ::djinni::JniClass<$jniHelper>::get();")
writeAlignedCall(w, "return {", r.fields, "}", f => {
val fieldId = "data.field_" + idJava.field(f.ident)
val jniFieldAccess = toJniCall(f.ty, (jt: String) => s"jniEnv->Get${jt}Field(j, $fieldId)")
jniMarshal.toCpp(f.ty, jniFieldAccess)
})
w.wl(";")
}
}
writeJniFiles(origin, params.nonEmpty, ident, refs, writeJniPrototype, writeJniBody)
}
......@@ -180,10 +180,9 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
val jniSelf = jniMarshal.helperClass(ident)
val cppSelf = cppMarshal.fqTypename(ident, i) + cppTypeArgs(typeParams)
val fqJniClassName = jniMarshal.fqHelperClass(ident)
val classLookup = jniMarshal.undecoratedTypename(ident, i)
val baseType = s"djinni::JniInterface<$cppSelf, $jniSelf>"
val baseType = s"::djinni::JniInterface<$cppSelf, $jniSelf>"
def writeJniPrototype(w: IndentWriter) {
writeJniTypeParams(w, typeParams)
......@@ -192,85 +191,92 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
w.wl(s"using CppType = std::shared_ptr<$cppSelf>;")
w.wl(s"using JniType = jobject;")
w.wl
w.wl(s"static jobject toJava(JNIEnv* jniEnv, std::shared_ptr<$cppSelf> c) { return djinni::JniClass<$fqJniClassName>::get()._toJava(jniEnv, c); }")
w.wl(s"static std::shared_ptr<$cppSelf> fromJava(JNIEnv* jniEnv, jobject j) { return djinni::JniClass<$fqJniClassName>::get()._fromJava(jniEnv, j); }")
w.wl(s"using Boxed = $jniSelf;")
w.wl
w.wl(s"~$jniSelf();")
w.wl
w.wl(s"static CppType toCpp(JNIEnv* jniEnv, JniType j) { return ::djinni::JniClass<$jniSelf>::get()._fromJava(jniEnv, j); }")
w.wl(s"static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) { return {jniEnv, ::djinni::JniClass<$jniSelf>::get()._toJava(jniEnv, c)}; }")
w.wl
w.wlOutdent("private:")
w.wl(s"$jniSelf();")
w.wl(s"friend ::djinni::JniClass<$jniSelf>;")
w.wl(s"friend $baseType;")
w.wl
if (i.ext.java) {
w.wl(s"const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass(${q(classLookup)}) };")
for (m <- i.methods) {
val javaMethodName = idJava.method(m.ident)
val javaMethodSig = q(toJavaMethodSig(spec.javaPackage, m.params, m.ret))
w.wl(s"const jmethodID method_$javaMethodName { djinni::jniGetMethodID(clazz.get(), ${q(javaMethodName)}, $javaMethodSig) };")
}
}
if (i.ext.java) {
w.wl
w.w(s"class JavaProxy final : djinni::JavaProxyCacheEntry, public $cppSelf").bracedSemi {
w.wl(s"class JavaProxy final : ::djinni::JavaProxyCacheEntry, public $cppSelf").bracedSemi {
w.wlOutdent(s"public:")
w.wl(s"JavaProxy(jobject obj);")
// w.wl(s"using JavaProxyCacheEntry::JavaProxyCacheEntry;")
w.wl(s"JavaProxy(JniType j);")
w.wl(s"~JavaProxy();")
w.wl
for (m <- i.methods) {
val ret = cppMarshal.fqReturnType(m.ret)
val params = m.params.map(p => cppMarshal.fqParamType(p.ty) + " " + idCpp.local(p.ident))
w.wl(s"virtual $ret ${idCpp.method(m.ident)}${params.mkString("(", ", ", ")")} override;")
w.wl(s"$ret ${idCpp.method(m.ident)}${params.mkString("(", ", ", ")")} override;")
}
w.wl
w.wlOutdent(s"private:")
w.wl(s"using djinni::JavaProxyCacheEntry::getGlobalRef;")
w.wl(s"friend class djinni::JniInterface<$cppSelf, $fqJniClassName>;")
w.wl(s"friend class djinni::JavaProxyCache<JavaProxy>;")
w.wl(s"using ::djinni::JavaProxyCacheEntry::getGlobalRef;")
w.wl(s"friend ::djinni::JniInterface<$cppSelf, ${withNs(Some(spec.jniNamespace), jniSelf)}>;")
w.wl(s"friend ::djinni::JavaProxyCache<JavaProxy>;")
}
w.wl
w.wl(s"const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass(${q(classLookup)}) };")
for (m <- i.methods) {
val javaMethodName = idJava.method(m.ident)
val javaMethodSig = q(jniMarshal.javaMethodSignature(m.params, m.ret))
w.wl(s"const jmethodID method_$javaMethodName { ::djinni::jniGetMethodID(clazz.get(), ${q(javaMethodName)}, $javaMethodSig) };")
}
}
w.wl
w.wlOutdent("private:")
w.wl(s"$jniSelf();")
w.wl(s"friend class djinni::JniClass<$fqJniClassName>;")
}
}
def writeJniBody(w: IndentWriter) {
// Defining ctor/dtor in the cpp file reduces build times
val baseClassParam = if (i.ext.cpp) q(classLookup+"$CppProxy") else ""
val jniSelfWithParams = jniSelf + typeParamsSignature(typeParams)
writeJniTypeParams(w, typeParams)
w.wl(s"$jniSelfWithParams::$jniSelf() : $baseType($baseClassParam) {}")
w.wl
writeJniTypeParams(w, typeParams)
w.wl(s"$jniSelf::$jniSelf() : $baseType($baseClassParam) {}")
w.wl(s"$jniSelfWithParams::~$jniSelf() = default;")
w.wl
if (i.ext.java) {
writeJniTypeParams(w, typeParams)
w.wl(s"$jniSelf::JavaProxy::JavaProxy(jobject obj) : JavaProxyCacheEntry(obj) {}")
w.wl(s"$jniSelfWithParams::JavaProxy::JavaProxy(JniType j) : JavaProxyCacheEntry(j) { }")
w.wl
writeJniTypeParams(w, typeParams)
w.wl(s"$jniSelfWithParams::JavaProxy::~JavaProxy() = default;")
w.wl
for (m <- i.methods) {
w.wl
val ret = cppMarshal.fqReturnType(m.ret)
val params = m.params.map(p => cppMarshal.fqParamType(p.ty) + " c_" + idCpp.local(p.ident))
val params = m.params.map(p => cppMarshal.fqParamType(p.ty) + " " + idCpp.local(p.ident))
writeJniTypeParams(w, typeParams)
w.w(s"$ret $jniSelf::JavaProxy::JavaProxy::${idCpp.method(m.ident)}${params.mkString("(", ", ", ")")}").bracedSemi {
w.wl(s"JNIEnv * const jniEnv = djinni::jniGetThreadEnv();")
w.wl(s"djinni::JniLocalScope jscope(jniEnv, 10);")
val jniArgs = mutable.ListBuffer[String]()
for (p <- m.params) {
val cppParamName = "c_" + idCpp.local(p.ident)
val jniLocal = "j_" + idCpp.local(p.ident)
val jniHelperClass = toJniHelperClass(p.ty)
val jniLocalRead = storeLocal(w, jniLocal, p.ty, s"$jniHelperClass::toJava(jniEnv, $cppParamName)")
jniArgs.append(jniLocalRead)
}
w.wl(s"const auto & data = djinni::JniClass<$fqJniClassName>::get();")
val argList = jniArgs.map(", "+_).mkString("")
w.w(s"$ret $jniSelfWithParams::JavaProxy::${idCpp.method(m.ident)}${params.mkString("(", ", ", ")")}").braced {
w.wl(s"auto jniEnv = ::djinni::jniGetThreadEnv();")
w.wl(s"::djinni::JniLocalScope jscope(jniEnv, 10);")
w.wl(s"const auto& data = ::djinni::JniClass<${withNs(Some(spec.jniNamespace), jniSelf)}>::get();")
val call = m.ret.fold("jniEnv->CallVoidMethod(")(r => toJniCall(r, (jt: String) => s"auto jret = jniEnv->Call${jt}Method("))
w.w(call)
val javaMethodName = idJava.method(m.ident)
m.ret match {
case Some(r) =>
val jniCall = toJniCall(r, (jt: String) => s"jniEnv->Call${jt}Method(getGlobalRef(), data.method_$javaMethodName$argList)")
val jretRead = storeLocal(w, "jret", r, jniCall)
w.wl(s"djinni::jniExceptionCheck(jniEnv);")
val jniHelperClass = toJniHelperClass(r)
w.wl(s"return $jniHelperClass::fromJava(jniEnv, $jretRead);")
case None =>
w.wl(s"jniEnv->CallVoidMethod(getGlobalRef(), data.method_$javaMethodName$argList);")
w.wl(s"djinni::jniExceptionCheck(jniEnv);")
w.w(s"getGlobalRef(), data.method_$javaMethodName")
if(!m.params.isEmpty){
w.wl(",")
writeAlignedCall(w, " " * call.length(), m.params, ")", p => {
val get = if(jniMarshal.isJavaHeapObject(p.ty)) ".get()" else ""
jniMarshal.fromCpp(p.ty, idCpp.local(p.ident)) + get
})
}
else
w.w(")")
w.wl(";")
w.wl(s"::djinni::jniExceptionCheck(jniEnv);")
m.ret.fold()(r => w.wl(s"return ${jniMarshal.toCpp(r, "jret")};"))
}
}
}
if (i.ext.cpp) {
w.wl(s"using namespace ::${spec.jniNamespace};")
// Generate CEXPORT functions for JNI to call.
val classIdentMunged = javaMarshal.fqTypename(ident, i)
.replaceAllLiterally("_", "_1")
......@@ -306,28 +312,13 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
val nativeAddon = if (m.static) "" else "native_"
nativeHook(nativeAddon + idJava.method(m.ident), m.static, m.params, m.ret, {
//w.wl(s"::${spec.jniNamespace}::JniLocalScope jscope(jniEnv, 10);")
if (!m.static) w.wl(s"const std::shared_ptr<$cppSelf> & ref = djinni::CppProxyHandle<$cppSelf>::get(nativeRef);")
for (p <- m.params) {
val jniHelperClass = toJniHelperClass(p.ty)
val cppType = cppMarshal.fqFieldType(p.ty)
val localVar = "c_" + idCpp.local(p.ident)
val paramName = "j_" + idJava.local(p.ident)
w.wl(s"$cppType $localVar = $jniHelperClass::fromJava(jniEnv, $paramName);")
}
val callArgs = m.params.map(p => "c_" + idCpp.local(p.ident)).mkString(", ")
if (!m.static) w.wl(s"const auto& ref = ::djinni::CppProxyHandle<$cppSelf>::get(nativeRef);")
val methodName = idCpp.method(m.ident)
val callExpr = if (m.static) s"$cppSelf::$methodName($callArgs)" else s"ref->$methodName($callArgs)"
w.wl
m.ret match {
case Some(r) =>
val cppRetType = cppMarshal.fqFieldType(r)
val jniHelperClass = toJniHelperClass(r)
w.wl(s"$cppRetType cr = $callExpr;")
w.wl
w.wl(s"return $jniHelperClass::toJava(jniEnv, cr);")
case None =>
w.wl(s"$callExpr;")
}
val ret = m.ret.fold("")(r => "auto r = ")
val call = if (m.static) s"$cppSelf::$methodName(" else s"ref->$methodName("
writeAlignedCall(w, ret + call, m.params, ")", p => jniMarshal.toCpp(p.ty, "j_" + idJava.local(p.ident)))
w.wl(";")
m.ret.fold()(r => w.wl(s"return ${jniMarshal.fromCpp(r, "r")}" + (if(jniMarshal.isJavaHeapObject(r)) ".release();" else ";")))
})
}
}
......@@ -352,47 +343,12 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
}
}
def toJavaMethodSig(javaPackage: Option[String], params: Iterable[Field], ret: Option[TypeRef]) = {
params.map(f => jniMarshal.typename(f.ty)).mkString("(", "", ")") + ret.fold("V")(jniMarshal.typename)
}
def writeJniTypeParams(w: IndentWriter, params: Seq[TypeParam]) {
if (params.isEmpty) return
w.wl("template " + params.map(p => "typename " + spec.jniClassIdentStyle(p.ident)).mkString("<", ", ", ">"))
}
def toJniHelperClass(ty: TypeRef, namespace: Option[String] = None): String = toJniHelperClass(ty.resolved, namespace)
def toJniHelperClass(tm: MExpr, namespace: Option[String]): String = {
def base(m: Meta, needRef: Boolean): String = m match {
case o: MOpaque =>
val name = o match {
case _: MPrimitive if !needRef => o.idlName + "::Unboxed"
case _ => o.idlName
}
withNs(Some("djinni"), jniBaseLibClassIdentStyle(name))
case d: MDef => spec.jniClassIdentStyle(d.name)
case p: MParam => idCpp.typeParam(p.name)
}
def expr(tm: MExpr, needRef: Boolean): String = {
val args = if (tm.args.isEmpty) "" else tm.args.map(expr(_, true)).mkString("<", ", ", ">")
base(tm.base, needRef) + args
}
// Hacky special case - HOptional needs an extra parameter that's the optional impl in use
tm.base match {
case MOptional => base(tm.base, false) + "<" + spec.cppOptionalTemplate + ", " + expr(tm.args.head, true) + ">"
case _ => expr(tm, false)
}
}
def toJniType(ty: TypeRef): String = toJniType(ty.resolved, false)
def toJniType(m: MExpr, needRef: Boolean): String = m.base match {
case p: MPrimitive => if (needRef) "jobject" else p.jniName
case MString => "jstring"
case MOptional => toJniType(m.args.head, true)
case MBinary => "jbyteArray"
case tp: MParam => spec.jniClassIdentStyle(tp.name) + "::JniType"
case _ => "jobject"
}
def typeParamsSignature(params: Seq[TypeParam]) = if(params.isEmpty) "" else params.map(p => spec.jniClassIdentStyle(p.ident)).mkString("<", ", ", ">")
def toJniCall(ty: TypeRef, f: String => String): String = toJniCall(ty.resolved, f, false)
def toJniCall(m: MExpr, f: String => String, needRef: Boolean): String = m.base match {
......@@ -403,24 +359,6 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
case _ => f("Object")
}
def isJavaHeapObject(ty: TypeRef): Boolean = isJavaHeapObject(ty.resolved.base)
def isJavaHeapObject(m: Meta): Boolean = m match {
case _: MPrimitive => false
case _ => true
}
def storeLocal(w: IndentWriter, name: String, ty: TypeRef, expr: String) = {
val jniTy = jniMarshal.fqFieldType(ty)
if (isJavaHeapObject(ty)) {
w.wl(s"djinni::LocalRef<$jniTy> $name(jniEnv, $expr);")
s"$name.get()"
} else {
w.wl(s"$jniTy $name = $expr;")
name
}
}
def cppTypeArgs(params: Seq[TypeParam]): String =
if (params.isEmpty) "" else params.map(p => idCpp.typeParam(p.ident)).mkString("<", ", ", ">")
}
......@@ -22,9 +22,16 @@ class JNIMarshal(spec: Spec) extends Marshal(spec) {
override def fieldType(tm: MExpr): String = paramType(tm)
override def fqFieldType(tm: MExpr): String = fqParamType(tm)
override def toCpp(tm: MExpr, expr: String): String = {
s"${helperClass(tm)}::toCpp(jniEnv, $expr)"
}
override def fromCpp(tm: MExpr, expr: String): String = {
s"${helperClass(tm)}::fromCpp(jniEnv, $expr)"
}
// Name for the autogenerated class containing field/method IDs and toJava()/fromJava() methods
def helperClass(name: String) = spec.jniClassIdentStyle(name)
def fqHelperClass(name: String) = withNs(Some(spec.jniNamespace), helperClass(name))
private def helperClass(tm: MExpr) = helperName(tm) + helperTemplates(tm)
def toJniType(ty: TypeRef): String = toJniType(ty.resolved, false)
def toJniType(m: MExpr, needRef: Boolean): String = m.base match {
......@@ -61,4 +68,54 @@ class JNIMarshal(spec: Spec) extends Marshal(spec) {
case d: MDef => s"L${undecoratedTypename(d.name, d.body)};"
}
def javaMethodSignature(params: Iterable[Field], ret: Option[TypeRef]) = {
params.map(f => typename(f.ty)).mkString("(", "", ")") + ret.fold("V")(typename)
}
private def helperName(tm: MExpr): String = tm.base match {
case d: MDef => withNs(Some(spec.jniNamespace), helperClass(d.name))
case o => withNs(Some("djinni"), o match {
case p: MPrimitive => p.idlName match {
case "i8" => "I8"
case "i16" => "I16"
case "i32" => "I32"
case "i64" => "I64"
case "f64" => "F64"
case "bool" => "Bool"
}
case MOptional => "Optional"
case MBinary => "Binary"
case MString => "String"
case MDate => "Date"
case MList => "List"
case MSet => "Set"
case MMap => "Map"
case d: MDef => throw new AssertionError("unreachable")
case p: MParam => throw new AssertionError("not applicable")
})
}
private def helperTemplates(tm: MExpr): String = {
def f() = if(tm.args.isEmpty) "" else tm.args.map(helperClass).mkString("<", ", ", ">")
tm.base match {
case MOptional =>
assert(tm.args.size == 1)
val argHelperClass = helperClass(tm.args.head)
s"<${spec.cppOptionalTemplate}, $argHelperClass>"
case MList | MSet =>
assert(tm.args.size == 1)
f
case MMap =>
assert(tm.args.size == 2)
f
case _ => f
}
}
def isJavaHeapObject(ty: TypeRef): Boolean = isJavaHeapObject(ty.resolved.base)
def isJavaHeapObject(m: Meta): Boolean = m match {
case _: MPrimitive => false
case _ => true
}
}
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "djinni_support.hpp"
#include <cstdlib>
namespace djinni {
class HBinary {
public:
using CppType = std::vector<uint8_t>;
using JniType = jbyteArray;
static std::vector<uint8_t> fromJava(JNIEnv * jniEnv, jbyteArray j) {
const auto deleter = [jniEnv, j] (void * c) {
jniEnv->ReleasePrimitiveArrayCritical(j, c, JNI_ABORT);
};
std::unique_ptr<uint8_t, decltype(deleter)> ptr(
reinterpret_cast<uint8_t *>(jniEnv->GetPrimitiveArrayCritical(j, nullptr)),
deleter);
jniExceptionCheck(jniEnv);
return std::vector<uint8_t>(ptr.get(), ptr.get() + jniEnv->GetArrayLength(j));
}
static jbyteArray toJava(JNIEnv* jniEnv, const std::vector<uint8_t> & c) {
LocalRef<jbyteArray> j(jniEnv, jniEnv->NewByteArray(c.size()));
DJINNI_ASSERT(j, jniEnv);
jniEnv->SetByteArrayRegion(j.get(), 0, c.size(),
reinterpret_cast<const jbyte *>(c.data()));
return j.release();
}
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "Primitive.hpp"
namespace djinni {
class HBool : public Primitive<HBool, bool, jboolean> {
HBool() : Primitive("java/lang/Boolean",
"valueOf", "(Z)Ljava/lang/Boolean;",
"booleanValue", "()Z") {}
friend class JniClass<HBool>;
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "djinni_support.hpp"
#include <chrono>
namespace djinni {
class HDateJniInfo {
public:
const GlobalRef<jclass> clazz { jniFindClass("java/util/Date") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "(J)V") };
const jmethodID method_get_time { jniGetMethodID(clazz.get(), "getTime", "()J") };
};
class HDate {
public:
using CppType = std::chrono::system_clock::time_point;
using JniType = jobject;
static std::chrono::system_clock::time_point fromJava(JNIEnv* jniEnv, jobject j) {
static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0);
assert(j != nullptr);
const auto & data = JniClass<HDateJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
const jlong time_millis = jniEnv->CallLongMethod(j, data.method_get_time);
return POSIX_EPOCH + std::chrono::milliseconds{time_millis};
}
static jobject toJava(JNIEnv* jniEnv, std::chrono::system_clock::time_point value) {
static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0);
const auto & data = JniClass<HDateJniInfo>::get();
const auto cpp_millis = std::chrono::duration_cast<std::chrono::milliseconds>(value - POSIX_EPOCH);
const jlong millis = static_cast<jlong>(cpp_millis.count());
LocalRef<jobject> j(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, millis));
jniExceptionCheck(jniEnv);
return j.release();
}
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "Primitive.hpp"
namespace djinni {
class HF64 : public Primitive<HF64, double, jdouble> {
HF64() : Primitive("java/lang/Double",
"valueOf", "(D)Ljava/lang/Double;",
"doubleValue", "()D") {}
friend class JniClass<HF64>;
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "Primitive.hpp"
namespace djinni {
class HI16 : public Primitive<HI16, int16_t, jshort> {
HI16() : Primitive("java/lang/Short",
"valueOf", "(S)Ljava/lang/Short;",
"shortValue", "()S") {}
friend class JniClass<HI16>;
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "Primitive.hpp"
namespace djinni {
class HI32 : public Primitive<HI32, int32_t, jint> {
HI32() : Primitive("java/lang/Integer",
"valueOf", "(I)Ljava/lang/Integer;",
"intValue", "()I") {}
friend class JniClass<HI32>;
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "Primitive.hpp"
namespace djinni {
class HI64 : public Primitive<HI64, int64_t, jlong> {
HI64() : Primitive("java/lang/Long",
"valueOf", "(J)Ljava/lang/Long;",
"longValue", "()J") {}
friend class JniClass<HI64>;
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "Primitive.hpp"
namespace djinni {
class HI8 : public Primitive<HI8, int8_t, jbyte> {
HI8() : Primitive("java/lang/Byte",
"valueOf", "(B)Ljava/lang/Byte;",
"byteValue", "()B") {}
friend class JniClass<HI8>;
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "djinni_support.hpp"
namespace djinni {
class HIteJniInfo {
public:
const GlobalRef<jclass> clazz { jniFindClass("java/util/Iterator") };
const jmethodID method_next { jniGetMethodID(clazz.get(), "next", "()Ljava/lang/Object;") };
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "djinni_support.hpp"
#include <set>
namespace djinni {
class HListJniInfo {
public:
const GlobalRef<jclass> clazz { jniFindClass("java/util/ArrayList") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "(I)V") };
const jmethodID method_add { jniGetMethodID(clazz.get(), "add", "(Ljava/lang/Object;)Z") };
const jmethodID method_get { jniGetMethodID(clazz.get(), "get", "(I)Ljava/lang/Object;") };
const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") };
};
template <class HElement>
class HList {
using ECppType = typename HElement::CppType;
using EJniType = typename HElement::JniType;
public:
using CppType = std::vector<ECppType>;
using JniType = jobject;
static std::vector<ECppType> fromJava(JNIEnv* jniEnv, jobject j) {
assert(j != nullptr);
const auto & data = JniClass<HListJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
jint size = jniEnv->CallIntMethod(j, data.method_size);
std::vector<ECppType> c;
c.reserve(size);
for (jint i = 0; i < size; i++) {
LocalRef<EJniType> je(jniEnv, static_cast<EJniType>(jniEnv->CallObjectMethod(j, data.method_get, i)));
jniExceptionCheck(jniEnv);
ECppType ce = HElement::fromJava(jniEnv, je.get());
c.push_back(std::move(ce));
}
return c;
}
static jobject toJava(JNIEnv* jniEnv, std::vector<ECppType> c) {
const auto & data = JniClass<HListJniInfo>::get();
assert(c.size() <= std::numeric_limits<jint>::max());
jint size = c.size();
LocalRef<jobject> j(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, size));
jniExceptionCheck(jniEnv);
for (const auto & ce : c) {
LocalRef<jobject> je(jniEnv, HElement::toJava(jniEnv, ce));
jniEnv->CallBooleanMethod(j.get(), data.method_add, je.get());
jniExceptionCheck(jniEnv);
}
return j.release();
}
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "HIteJniInfo.hpp"
#include "djinni_support.hpp"
namespace djinni {
class HMapJniInfo {
public:
const GlobalRef<jclass> clazz { jniFindClass("java/util/HashMap") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "()V") };
const jmethodID method_put { jniGetMethodID(clazz.get(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") };
const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") };
const jmethodID method_entrySet { jniGetMethodID(clazz.get(), "entrySet", "()Ljava/util/Set;") };
};
class HEntrySetJniInfo {
public:
const GlobalRef<jclass> clazz { jniFindClass("java/util/Set") };
const jmethodID method_iterator { jniGetMethodID(clazz.get(), "iterator", "()Ljava/util/Iterator;") };
};
class HEntryJniInfo {
public:
const GlobalRef<jclass> clazz { jniFindClass("java/util/Map$Entry") };
const jmethodID method_getKey { jniGetMethodID(clazz.get(), "getKey", "()Ljava/lang/Object;") };
const jmethodID method_getValue { jniGetMethodID(clazz.get(), "getValue", "()Ljava/lang/Object;") };
};
template <class HKey, class HValue>
class HMap {
using KCppType = typename HKey::CppType;
using KJniType = typename HKey::JniType;
using VCppType = typename HValue::CppType;
using VJniType = typename HValue::JniType;
public:
using CppType = std::unordered_map<KCppType, VCppType>;
using JniType = jobject;
static std::unordered_map<KCppType, VCppType> fromJava(JNIEnv* jniEnv, jobject j) {
assert(j != nullptr);
const auto & data = JniClass<HMapJniInfo>::get();
const auto & entrySetData = JniClass<HEntrySetJniInfo>::get();
const auto & entryData = JniClass<HEntryJniInfo>::get();
const auto & iteData = JniClass<HIteJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
jint size = jniEnv->CallIntMethod(j, data.method_size);
LocalRef<jobject> entrySet(jniEnv, jniEnv->CallObjectMethod(j, data.method_entrySet));
std::unordered_map<KCppType, VCppType> c;
c.reserve(size);
LocalRef<jobject> it(jniEnv, jniEnv->CallObjectMethod(entrySet.get(), entrySetData.method_iterator));
for (jint i = 0; i < size; i++) {
LocalRef<jobject> je(jniEnv, jniEnv->CallObjectMethod(it.get(), iteData.method_next));
LocalRef<KJniType> jKey(jniEnv, static_cast<KJniType>(jniEnv->CallObjectMethod(je.get(), entryData.method_getKey)));
LocalRef<VJniType> jValue(jniEnv, static_cast<VJniType>(jniEnv->CallObjectMethod(je.get(), entryData.method_getValue)));
jniExceptionCheck(jniEnv);
c.emplace(HKey::fromJava(jniEnv, jKey.get()),
HValue::fromJava(jniEnv, jValue.get()));
}
return c;
}
static jobject toJava(JNIEnv* jniEnv, std::unordered_map<KCppType, VCppType> c) {
const auto & data = JniClass<HMapJniInfo>::get();
assert(c.size() <= std::numeric_limits<jint>::max());
jint size = c.size();
LocalRef<jobject> j(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, size));
jniExceptionCheck(jniEnv);
for (const auto & ce : c) {
LocalRef<jobject> jKey(jniEnv, HKey::toJava(jniEnv, ce.first));
LocalRef<jobject> jValue(jniEnv, HValue::toJava(jniEnv, ce.second));
jniEnv->CallObjectMethod(j.get(), data.method_put, jKey.get(), jValue.get());
jniExceptionCheck(jniEnv);
}
return j.release();
}
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "djinni_support.hpp"
namespace djinni {
template <template <class> class Optional, class HElement>
class HOptional {
using ECppType = typename HElement::CppType;
using EJniType = typename HElement::JniType;
public:
using CppType = Optional<ECppType>;
using JniType = EJniType;
static CppType fromJava(JNIEnv* jniEnv, JniType j) {
if (j != nullptr) {
return HElement::fromJava(jniEnv, j);
}
return {};
}
static JniType toJava(JNIEnv* jniEnv, const CppType & c) {
if (c) {
return HElement::toJava(jniEnv, *c);
}
return nullptr;
}
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "HIteJniInfo.hpp"
#include "djinni_support.hpp"
namespace djinni {
class HSetJniInfo {
public:
const GlobalRef<jclass> clazz { jniFindClass("java/util/HashSet") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "()V") };
const jmethodID method_add { jniGetMethodID(clazz.get(), "add", "(Ljava/lang/Object;)Z") };
const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") };
const jmethodID method_iterator { jniGetMethodID(clazz.get(), "iterator", "()Ljava/util/Iterator;") };
};
template <class HElement>
class HSet {
using ECppType = typename HElement::CppType;
using EJniType = typename HElement::JniType;
public:
using CppType = std::unordered_set<ECppType>;
using JniType = jobject;
static std::unordered_set<ECppType> fromJava(JNIEnv* jniEnv, jobject j) {
assert(j != nullptr);
const auto & data = JniClass<HSetJniInfo>::get();
const auto & iteData = JniClass<HIteJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
jint size = jniEnv->CallIntMethod(j, data.method_size);
std::unordered_set<ECppType> c;
LocalRef<jobject> it(jniEnv, jniEnv->CallObjectMethod(j, data.method_iterator));
for (jint i = 0; i < size; i++) {
LocalRef<EJniType> je(jniEnv, static_cast<EJniType>(jniEnv->CallObjectMethod(it.get(), iteData.method_next)));
jniExceptionCheck(jniEnv);
c.insert(HElement::fromJava(jniEnv, je.get()));
}
return c;
}
static jobject toJava(JNIEnv* jniEnv, std::unordered_set<ECppType> c) {
const auto & data = JniClass<HSetJniInfo>::get();
LocalRef<jobject> j(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor));
jniExceptionCheck(jniEnv);
for (const auto & ce : c) {
LocalRef<jobject> je(jniEnv, HElement::toJava(jniEnv, ce));
jniEnv->CallBooleanMethod(j.get(), data.method_add, je.get());
jniExceptionCheck(jniEnv);
}
return j.release();
}
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "djinni_support.hpp"
namespace djinni {
class HString {
public:
using CppType = std::string;
using JniType = jstring;
static std::string fromJava(JNIEnv* jniEnv, jstring j) {
assert(j != nullptr);
return jniUTF8FromString(jniEnv, j);
}
static jstring toJava(JNIEnv* jniEnv, const std::string & c) {
return jniStringFromUTF8(jniEnv, c);
}
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "djinni_support.hpp"
#include <cassert>
#include <chrono>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
namespace djinni
{
template<class Self, class CppT, class JniT>
class Primitive
{
public:
using CppType = CppT;
using JniType = JniT;
static CppType toCpp(JNIEnv* /*jniEnv*/, JniType j) noexcept { return static_cast<CppType>(j); }
static JniType fromCpp(JNIEnv* /*jniEnv*/, CppType c) noexcept { return static_cast<JniType>(c); }
struct Boxed
{
using JniType = jobject;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
assert(j != nullptr);
const auto& data = JniClass<Self>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto ret = Primitive::toCpp(jniEnv, Self::unbox(jniEnv, data.method_unbox, j));
jniExceptionCheck(jniEnv);
return ret;
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, CppType c)
{
const auto& data = JniClass<Self>::get();
auto ret = jniEnv->CallStaticObjectMethod(data.clazz.get(), data.method_box, Primitive::fromCpp(jniEnv, c));
jniExceptionCheck(jniEnv);
return {jniEnv, ret};
}
};
protected:
Primitive(const char* javaClassSpec,
const char* staticBoxMethod,
const char* staticBoxMethodSignature,
const char* unboxMethod,
const char* unboxMethodSignature)
: clazz(jniFindClass(javaClassSpec))
, method_box(jniGetStaticMethodID(clazz.get(), staticBoxMethod, staticBoxMethodSignature))
, method_unbox(jniGetMethodID(clazz.get(), unboxMethod, unboxMethodSignature))
{}
private:
const GlobalRef<jclass> clazz;
const jmethodID method_box;
const jmethodID method_unbox;
};
class Bool : public Primitive<Bool, bool, jboolean>
{
Bool() : Primitive("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", "booleanValue", "()Z") {}
friend JniClass<Bool>;
friend Primitive<Bool, bool, jboolean>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) noexcept { return jniEnv->CallBooleanMethod(j, method); }
};
class I8 : public Primitive<I8, int8_t, jbyte>
{
I8() : Primitive("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", "byteValue", "()B") {}
friend JniClass<I8>;
friend Primitive<I8, int8_t, jbyte>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) noexcept { return jniEnv->CallByteMethod(j, method); }
};
class I16 : public Primitive<I16, int16_t, jshort>
{
I16() : Primitive("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", "shortValue", "()S") {}
friend JniClass<I16>;
friend Primitive<I16, int16_t, jshort>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) noexcept { return jniEnv->CallShortMethod(j, method); }
};
class I32 : public Primitive<I32, int32_t, jint>
{
I32() : Primitive("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", "intValue", "()I") {}
friend JniClass<I32>;
friend Primitive<I32, int32_t, jint>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) noexcept { return jniEnv->CallIntMethod(j, method); }
};
class I64 : public Primitive<I64, int64_t, jlong>
{
I64() : Primitive("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", "longValue", "()J") {}
friend JniClass<I64>;
friend Primitive<I64, int64_t, jlong>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) noexcept { return jniEnv->CallLongMethod(j, method); }
};
class F64 : public Primitive<F64, double, jdouble>
{
F64() : Primitive("java/lang/Dobule", "valueOf", "(D)Ljava/lang/Double;", "doubleValue", "()D") {}
friend JniClass<F64>;
friend Primitive<F64, double, jdouble>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) noexcept { return jniEnv->CallDoubleMethod(j, method); }
};
struct String
{
using CppType = std::string;
using JniType = jstring;
using Boxed = String;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
assert(j != nullptr);
return jniUTF8FromString(jniEnv, j);
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{
return {jniEnv, jniStringFromUTF8(jniEnv, c.c_str())};
}
};
struct Binary
{
using CppType = std::vector<uint8_t>;
using JniType = jbyteArray;
using Boxed = Binary;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
assert(j != nullptr);
auto deleter = [jniEnv, j] (void* c) { jniEnv->ReleasePrimitiveArrayCritical(j, c, JNI_ABORT); };
std::unique_ptr<uint8_t, decltype(deleter)> ptr(reinterpret_cast<uint8_t*>(jniEnv->GetPrimitiveArrayCritical(j, nullptr)),
deleter);
jniExceptionCheck(jniEnv);
return {ptr.get(), ptr.get() + jniEnv->GetArrayLength(j)};
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{
assert(c.size() <= std::numeric_limits<jsize>::max());
auto j = LocalRef<jbyteArray>(jniEnv, jniEnv->NewByteArray(static_cast<jsize>(c.size())));
jniExceptionCheck(jniEnv);
// Using .data() on an empty vector is UB
if(!c.empty())
{
jniEnv->SetByteArrayRegion(j.get(), 0, c.size(), reinterpret_cast<const jbyte*>(c.data()));
}
return j;
}
};
struct Date
{
using CppType = std::chrono::system_clock::time_point;
using JniType = jobject;
using Boxed = Date;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0);
assert(j != nullptr);
const auto & data = JniClass<Date>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto time_millis = jniEnv->CallLongMethod(j, data.method_get_time);
return POSIX_EPOCH + std::chrono::milliseconds{time_millis};
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{
static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0);
const auto & data = JniClass<Date>::get();
const auto cpp_millis = std::chrono::duration_cast<std::chrono::milliseconds>(c - POSIX_EPOCH);
const jlong millis = static_cast<jlong>(cpp_millis.count());
auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, millis));
jniExceptionCheck(jniEnv);
return j;
}
private:
Date() = default;
friend ::djinni::JniClass<Date>;
const GlobalRef<jclass> clazz { jniFindClass("java/util/Date") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "(J)V") };
const jmethodID method_get_time { jniGetMethodID(clazz.get(), "getTime", "()J") };
};
template <template <class> class OptionalType, class T>
struct Optional
{
using CppType = OptionalType<typename T::CppType>;
using JniType = typename T::Boxed::JniType;
using Boxed = Optional;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
return j ? CppType(T::Boxed::toCpp(jniEnv, j)) : CppType();
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{
return c ? T::Boxed::fromCpp(jniEnv, *c) : LocalRef<JniType>{};
}
};
struct ListJniInfo
{
const GlobalRef<jclass> clazz { jniFindClass("java/util/ArrayList") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "(I)V") };
const jmethodID method_add { jniGetMethodID(clazz.get(), "add", "(Ljava/lang/Object;)Z") };
const jmethodID method_get { jniGetMethodID(clazz.get(), "get", "(I)Ljava/lang/Object;") };
const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") };
};
template <class T>
class List
{
using ECppType = typename T::CppType;
using EJniType = typename T::Boxed::JniType;
public:
using CppType = std::vector<ECppType>;
using JniType = jobject;
using Boxed = List;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
assert(j != nullptr);
const auto& data = JniClass<ListJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto size = jniEnv->CallIntMethod(j, data.method_size);
auto c = CppType();
c.reserve(size);
for(jint i = 0; i < size; ++i)
{
auto je = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_get, i));
jniExceptionCheck(jniEnv);
c.push_back(T::Boxed::toCpp(jniEnv, static_cast<EJniType>(je.get())));
}
return c;
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{
const auto& data = JniClass<ListJniInfo>::get();
assert(c.size() <= std::numeric_limits<jint>::max());
auto size = static_cast<jint>(c.size());
auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, size));
jniExceptionCheck(jniEnv);
for(const auto& ce : c)
{
auto je = T::Boxed::fromCpp(jniEnv, ce);
jniEnv->CallBooleanMethod(j, data.method_add, je.get());
jniExceptionCheck(jniEnv);
}
return j;
}
};
struct IteratorJniInfo
{
const GlobalRef<jclass> clazz { jniFindClass("java/util/Iterator") };
const jmethodID method_next { jniGetMethodID(clazz.get(), "next", "()Ljava/lang/Object;") };
};
struct SetJniInfo
{
const GlobalRef<jclass> clazz { jniFindClass("java/util/HashSet") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "()V") };
const jmethodID method_add { jniGetMethodID(clazz.get(), "add", "(Ljava/lang/Object;)Z") };
const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") };
const jmethodID method_iterator { jniGetMethodID(clazz.get(), "iterator", "()Ljava/util/Iterator;") };
};
template <class T>
class Set
{
using ECppType = typename T::CppType;
using EJniType = typename T::Boxed::JniType;
public:
using CppType = std::unordered_set<ECppType>;
using JniType = jobject;
using Boxed = Set;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
assert(j != nullptr);
const auto& data = JniClass<SetJniInfo>::get();
const auto& iteData = JniClass<IteratorJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto size = jniEnv->CallIntMethod(j, data.method_size);
auto c = CppType();
auto it = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_iterator));
for(jint i = 0; i < size; ++i)
{
auto je = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(it, iteData.method_next));
jniExceptionCheck(jniEnv);
c.insert(T::Boxed::toCpp(jniEnv, static_cast<EJniType>(je.get())));
}
return c;
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{
assert(c.size() <= std::numeric_limits<jint>::max());
const auto& data = JniClass<SetJniInfo>::get();
auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor));
jniExceptionCheck(jniEnv);
for(const auto& ce : c)
{
auto je = T::fromCpp(jniEnv, ce);
jniEnv->CallBooleanMethod(j, data.method_add, je.get());
jniExceptionCheck(jniEnv);
}
return j;
}
};
struct MapJniInfo
{
const GlobalRef<jclass> clazz { jniFindClass("java/util/HashMap") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "()V") };
const jmethodID method_put { jniGetMethodID(clazz.get(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") };
const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") };
const jmethodID method_entrySet { jniGetMethodID(clazz.get(), "entrySet", "()Ljava/util/Set;") };
};
struct EntrySetJniInfo
{
const GlobalRef<jclass> clazz { jniFindClass("java/util/Set") };
const jmethodID method_iterator { jniGetMethodID(clazz.get(), "iterator", "()Ljava/util/Iterator;") };
};
struct EntryJniInfo
{
const GlobalRef<jclass> clazz { jniFindClass("java/util/Map$Entry") };
const jmethodID method_getKey { jniGetMethodID(clazz.get(), "getKey", "()Ljava/lang/Object;") };
const jmethodID method_getValue { jniGetMethodID(clazz.get(), "getValue", "()Ljava/lang/Object;") };
};
template <class Key, class Value>
class Map
{
using CppKeyType = typename Key::CppType;
using CppValueType = typename Value::CppType;
using JniKeyType = typename Key::Boxed::JniType;
using JniValueType = typename Value::Boxed::JniType;
public:
using CppType = std::unordered_map<CppKeyType, CppValueType>;
using JniType = jobject;
using Boxed = Map;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
assert(j != nullptr);
const auto& data = JniClass<MapJniInfo>::get();
const auto& entrySetData = JniClass<EntrySetJniInfo>::get();
const auto& entryData = JniClass<EntryJniInfo>::get();
const auto& iteData = JniClass<IteratorJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto size = jniEnv->CallIntMethod(j, data.method_size);
auto entrySet = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_entrySet));
auto c = CppType();
c.reserve(size);
auto it = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(entrySet, entrySetData.method_iterator));
for(jint i = 0; i < size; ++i)
{
auto je = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(it, iteData.method_next));
auto jKey = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(je, entryData.method_getKey));
auto jValue = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(je, entryData.method_getValue));
jniExceptionCheck(jniEnv);
c.emplace(Key::Boxed::toCpp(jniEnv, static_cast<JniKeyType>(jKey.get())),
Value::Boxed::toCpp(jniEnv, static_cast<JniValueType>(jValue.get())));
}
return c;
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{
const auto& data = JniClass<MapJniInfo>::get();
assert(c.size() <= std::numeric_limits<jint>::max());
auto size = c.size();
auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, size));
jniExceptionCheck(jniEnv);
for(const auto& ce : c)
{
auto jKey = Key::Boxed::fromCpp(jniEnv, ce.first);
auto jValue = Value::Boxed::fromCpp(jniEnv, ce.second);
jniEnv->CallObjectMethod(j, data.method_put, jKey.get(), jValue.get());
jniExceptionCheck(jniEnv);
}
return j;
}
};
} // namespace djinni
//
// Copyright 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma once
#include "djinni_support.hpp"
namespace djinni {
template <class JniType>
JniType jniUnboxMethodCall(JNIEnv* jniEnv, jmethodID method, jobject thiz);
template <class Self, class _CppType, class UnboxedJniType>
class Primitive {
public:
using CppType = _CppType;
using JniType = jobject;
static CppType fromJava(JNIEnv* jniEnv, jobject j) {
assert(j != nullptr);
const auto & data = JniClass<Self>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
UnboxedJniType jni = jniUnboxMethodCall<UnboxedJniType>(jniEnv, data.method_unbox, j);
CppType c = Primitive::Unboxed::fromJava(jniEnv, jni);
return c;
}
static jobject toJava(JNIEnv* jniEnv, CppType c) {
const auto & data = JniClass<Self>::get();
UnboxedJniType jni = Primitive::Unboxed::toJava(jniEnv, c);
jobject j = jniEnv->CallStaticObjectMethod(data.clazz.get(), data.method_box, jni);
jniExceptionCheck(jniEnv);
return j;
}
class Unboxed {
public:
static CppType fromJava(JNIEnv* /*jniEnv*/, UnboxedJniType j) {
return static_cast<CppType>(j);
}
static UnboxedJniType toJava(JNIEnv* /*jniEnv*/, CppType c) {
return static_cast<UnboxedJniType>(c);
}
};
protected:
Primitive(
const char* javaClassSpec,
const char* staticBoxMethod,
const char* staticBoxMethodSignature,
const char* unboxMethod,
const char* unboxMethodSignature) :
clazz(jniFindClass(javaClassSpec)),
method_box(jniGetStaticMethodID(clazz.get(), staticBoxMethod, staticBoxMethodSignature)),
method_unbox(jniGetMethodID(clazz.get(), unboxMethod, unboxMethodSignature)) {}
private:
const GlobalRef<jclass> clazz;
const jmethodID method_box;
const jmethodID method_unbox;
};
template <>
inline
jbyte jniUnboxMethodCall<jbyte>(JNIEnv* jniEnv, jmethodID method, jobject thiz) {
jbyte ret = jniEnv->CallByteMethod(thiz, method);
jniExceptionCheck(jniEnv);
return ret;
}
template <>
inline
jshort jniUnboxMethodCall<jshort>(JNIEnv* jniEnv, jmethodID method, jobject thiz) {
jshort ret = jniEnv->CallShortMethod(thiz, method);
jniExceptionCheck(jniEnv);
return ret;
}
template <>
inline
jint jniUnboxMethodCall<jint>(JNIEnv* jniEnv, jmethodID method, jobject thiz) {
jint ret = jniEnv->CallIntMethod(thiz, method);
jniExceptionCheck(jniEnv);
return ret;
}
template <>
inline
jlong jniUnboxMethodCall<jlong>(JNIEnv* jniEnv, jmethodID method, jobject thiz) {
jlong ret = jniEnv->CallLongMethod(thiz, method);
jniExceptionCheck(jniEnv);
return ret;
}
template <>
inline
jboolean jniUnboxMethodCall<jboolean>(JNIEnv* jniEnv, jmethodID method, jobject thiz) {
jboolean ret = jniEnv->CallBooleanMethod(thiz, method);
jniExceptionCheck(jniEnv);
return ret;
}
template <>
inline
jdouble jniUnboxMethodCall<jdouble>(JNIEnv* jniEnv, jmethodID method, jobject thiz) {
jdouble ret = jniEnv->CallDoubleMethod(thiz, method);
jniExceptionCheck(jniEnv);
return ret;
}
} // namespace djinni
......@@ -91,6 +91,10 @@ public:
explicit LocalRef(PointerType localRef)
: std::unique_ptr<typename std::remove_pointer<PointerType>::type, LocalRefDeleter>(
localRef) {}
// Allow implicit conversion to PointerType so it can be passed
// as argument to JNI functions expecting PointerType.
// All functions creating new local references should return LocalRef instead of PointerType
operator PointerType() const { return this->get(); }
};
/*
......
......@@ -2,41 +2,40 @@
// This file generated by Djinni from inttypes.djinni
#include "NativeAssortedIntegers.hpp" // my header
#include "HI16.hpp"
#include "HI32.hpp"
#include "HI64.hpp"
#include "HI8.hpp"
#include "HOptional.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativeAssortedIntegers::toJava(JNIEnv* jniEnv, ::AssortedIntegers c) {
jbyte j_eight = ::djinni::HI8::Unboxed::toJava(jniEnv, c.eight);
jshort j_sixteen = ::djinni::HI16::Unboxed::toJava(jniEnv, c.sixteen);
jint j_thirtytwo = ::djinni::HI32::Unboxed::toJava(jniEnv, c.thirtytwo);
jlong j_sixtyfour = ::djinni::HI64::Unboxed::toJava(jniEnv, c.sixtyfour);
djinni::LocalRef<jobject> j_o_eight(jniEnv, ::djinni::HOptional<std::experimental::optional, ::djinni::HI8>::toJava(jniEnv, c.o_eight));
djinni::LocalRef<jobject> j_o_sixteen(jniEnv, ::djinni::HOptional<std::experimental::optional, ::djinni::HI16>::toJava(jniEnv, c.o_sixteen));
djinni::LocalRef<jobject> j_o_thirtytwo(jniEnv, ::djinni::HOptional<std::experimental::optional, ::djinni::HI32>::toJava(jniEnv, c.o_thirtytwo));
djinni::LocalRef<jobject> j_o_sixtyfour(jniEnv, ::djinni::HOptional<std::experimental::optional, ::djinni::HI64>::toJava(jniEnv, c.o_sixtyfour));
const auto & data = djinni::JniClass<::djinni_generated::NativeAssortedIntegers>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_eight, j_sixteen, j_thirtytwo, j_sixtyfour, j_o_eight.get(), j_o_sixteen.get(), j_o_thirtytwo.get(), j_o_sixtyfour.get());
djinni::jniExceptionCheck(jniEnv);
NativeAssortedIntegers::NativeAssortedIntegers() = default;
NativeAssortedIntegers::~NativeAssortedIntegers() = default;
auto NativeAssortedIntegers::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeAssortedIntegers>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::I8::fromCpp(jniEnv, c.eight),
::djinni::I16::fromCpp(jniEnv, c.sixteen),
::djinni::I32::fromCpp(jniEnv, c.thirtytwo),
::djinni::I64::fromCpp(jniEnv, c.sixtyfour),
::djinni::Optional<std::experimental::optional, ::djinni::I8>::fromCpp(jniEnv, c.o_eight).get(),
::djinni::Optional<std::experimental::optional, ::djinni::I16>::fromCpp(jniEnv, c.o_sixteen).get(),
::djinni::Optional<std::experimental::optional, ::djinni::I32>::fromCpp(jniEnv, c.o_thirtytwo).get(),
::djinni::Optional<std::experimental::optional, ::djinni::I64>::fromCpp(jniEnv, c.o_sixtyfour).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::AssortedIntegers NativeAssortedIntegers::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeAssortedIntegers::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeAssortedIntegers>::get();
return ::AssortedIntegers(
::djinni::HI8::Unboxed::fromJava(jniEnv, jniEnv->GetByteField(j, data.field_mEight)),
::djinni::HI16::Unboxed::fromJava(jniEnv, jniEnv->GetShortField(j, data.field_mSixteen)),
::djinni::HI32::Unboxed::fromJava(jniEnv, jniEnv->GetIntField(j, data.field_mThirtytwo)),
::djinni::HI64::Unboxed::fromJava(jniEnv, jniEnv->GetLongField(j, data.field_mSixtyfour)),
::djinni::HOptional<std::experimental::optional, ::djinni::HI8>::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mOEight)).get()),
::djinni::HOptional<std::experimental::optional, ::djinni::HI16>::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mOSixteen)).get()),
::djinni::HOptional<std::experimental::optional, ::djinni::HI32>::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mOThirtytwo)).get()),
::djinni::HOptional<std::experimental::optional, ::djinni::HI64>::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mOSixtyfour)).get()));
const auto& data = ::djinni::JniClass<NativeAssortedIntegers>::get();
return {::djinni::I8::toCpp(jniEnv, jniEnv->GetByteField(j, data.field_mEight)),
::djinni::I16::toCpp(jniEnv, jniEnv->GetShortField(j, data.field_mSixteen)),
::djinni::I32::toCpp(jniEnv, jniEnv->GetIntField(j, data.field_mThirtytwo)),
::djinni::I64::toCpp(jniEnv, jniEnv->GetLongField(j, data.field_mSixtyfour)),
::djinni::Optional<std::experimental::optional, ::djinni::I8>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mOEight)),
::djinni::Optional<std::experimental::optional, ::djinni::I16>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mOSixteen)),
::djinni::Optional<std::experimental::optional, ::djinni::I32>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mOThirtytwo)),
::djinni::Optional<std::experimental::optional, ::djinni::I64>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mOSixtyfour))};
}
} // namespace djinni_generated
......@@ -13,23 +13,27 @@ public:
using CppType = ::AssortedIntegers;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::AssortedIntegers);
static ::AssortedIntegers fromJava(JNIEnv*, jobject);
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/AssortedIntegers") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(BSIJLjava/lang/Byte;Ljava/lang/Short;Ljava/lang/Integer;Ljava/lang/Long;)V") };
const jfieldID field_mEight { djinni::jniGetFieldID(clazz.get(), "mEight", "B") };
const jfieldID field_mSixteen { djinni::jniGetFieldID(clazz.get(), "mSixteen", "S") };
const jfieldID field_mThirtytwo { djinni::jniGetFieldID(clazz.get(), "mThirtytwo", "I") };
const jfieldID field_mSixtyfour { djinni::jniGetFieldID(clazz.get(), "mSixtyfour", "J") };
const jfieldID field_mOEight { djinni::jniGetFieldID(clazz.get(), "mOEight", "Ljava/lang/Byte;") };
const jfieldID field_mOSixteen { djinni::jniGetFieldID(clazz.get(), "mOSixteen", "Ljava/lang/Short;") };
const jfieldID field_mOThirtytwo { djinni::jniGetFieldID(clazz.get(), "mOThirtytwo", "Ljava/lang/Integer;") };
const jfieldID field_mOSixtyfour { djinni::jniGetFieldID(clazz.get(), "mOSixtyfour", "Ljava/lang/Long;") };
using Boxed = NativeAssortedIntegers;
~NativeAssortedIntegers();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeAssortedIntegers() {}
friend class djinni::JniClass<::djinni_generated::NativeAssortedIntegers>;
NativeAssortedIntegers();
friend ::djinni::JniClass<NativeAssortedIntegers>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/AssortedIntegers") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(BSIJLjava/lang/Byte;Ljava/lang/Short;Ljava/lang/Integer;Ljava/lang/Long;)V") };
const jfieldID field_mEight { ::djinni::jniGetFieldID(clazz.get(), "mEight", "B") };
const jfieldID field_mSixteen { ::djinni::jniGetFieldID(clazz.get(), "mSixteen", "S") };
const jfieldID field_mThirtytwo { ::djinni::jniGetFieldID(clazz.get(), "mThirtytwo", "I") };
const jfieldID field_mSixtyfour { ::djinni::jniGetFieldID(clazz.get(), "mSixtyfour", "J") };
const jfieldID field_mOEight { ::djinni::jniGetFieldID(clazz.get(), "mOEight", "Ljava/lang/Byte;") };
const jfieldID field_mOSixteen { ::djinni::jniGetFieldID(clazz.get(), "mOSixteen", "Ljava/lang/Short;") };
const jfieldID field_mOThirtytwo { ::djinni::jniGetFieldID(clazz.get(), "mOThirtytwo", "Ljava/lang/Integer;") };
const jfieldID field_mOSixtyfour { ::djinni::jniGetFieldID(clazz.get(), "mOSixtyfour", "Ljava/lang/Long;") };
};
} // namespace djinni_generated
......@@ -2,27 +2,29 @@
// This file generated by Djinni from client_interface.djinni
#include "NativeClientInterface.hpp" // my header
#include "HI64.hpp"
#include "HOptional.hpp"
#include "HString.hpp"
#include "Marshal.hpp"
#include "NativeClientReturnedRecord.hpp"
namespace djinni_generated {
NativeClientInterface::NativeClientInterface() : djinni::JniInterface<::ClientInterface, NativeClientInterface>() {}
NativeClientInterface::JavaProxy::JavaProxy(jobject obj) : JavaProxyCacheEntry(obj) {}
::ClientReturnedRecord NativeClientInterface::JavaProxy::JavaProxy::get_record(int64_t c_record_id, const std::string & c_utf8string, const std::experimental::optional<std::string> & c_misc) {
JNIEnv * const jniEnv = djinni::jniGetThreadEnv();
djinni::JniLocalScope jscope(jniEnv, 10);
jlong j_record_id = ::djinni::HI64::Unboxed::toJava(jniEnv, c_record_id);
djinni::LocalRef<jstring> j_utf8string(jniEnv, ::djinni::HString::toJava(jniEnv, c_utf8string));
djinni::LocalRef<jstring> j_misc(jniEnv, ::djinni::HOptional<std::experimental::optional, ::djinni::HString>::toJava(jniEnv, c_misc));
const auto & data = djinni::JniClass<::djinni_generated::NativeClientInterface>::get();
djinni::LocalRef<jobject> jret(jniEnv, jniEnv->CallObjectMethod(getGlobalRef(), data.method_getRecord, j_record_id, j_utf8string.get(), j_misc.get()));
djinni::jniExceptionCheck(jniEnv);
return NativeClientReturnedRecord::fromJava(jniEnv, jret.get());
};
NativeClientInterface::NativeClientInterface() : ::djinni::JniInterface<::ClientInterface, NativeClientInterface>() {}
NativeClientInterface::~NativeClientInterface() = default;
NativeClientInterface::JavaProxy::JavaProxy(JniType j) : JavaProxyCacheEntry(j) { }
NativeClientInterface::JavaProxy::~JavaProxy() = default;
::ClientReturnedRecord NativeClientInterface::JavaProxy::get_record(int64_t record_id, const std::string & utf8string, const std::experimental::optional<std::string> & misc) {
auto jniEnv = ::djinni::jniGetThreadEnv();
::djinni::JniLocalScope jscope(jniEnv, 10);
const auto& data = ::djinni::JniClass<::djinni_generated::NativeClientInterface>::get();
auto jret = jniEnv->CallObjectMethod(getGlobalRef(), data.method_getRecord,
::djinni::I64::fromCpp(jniEnv, record_id),
::djinni::String::fromCpp(jniEnv, utf8string).get(),
::djinni::Optional<std::experimental::optional, ::djinni::String>::fromCpp(jniEnv, misc).get());
::djinni::jniExceptionCheck(jniEnv);
return ::djinni_generated::NativeClientReturnedRecord::toCpp(jniEnv, jret);
}
} // namespace djinni_generated
......@@ -8,31 +8,39 @@
namespace djinni_generated {
class NativeClientInterface final : djinni::JniInterface<::ClientInterface, NativeClientInterface> {
class NativeClientInterface final : ::djinni::JniInterface<::ClientInterface, NativeClientInterface> {
public:
using CppType = std::shared_ptr<::ClientInterface>;
using JniType = jobject;
static jobject toJava(JNIEnv* jniEnv, std::shared_ptr<::ClientInterface> c) { return djinni::JniClass<::djinni_generated::NativeClientInterface>::get()._toJava(jniEnv, c); }
static std::shared_ptr<::ClientInterface> fromJava(JNIEnv* jniEnv, jobject j) { return djinni::JniClass<::djinni_generated::NativeClientInterface>::get()._fromJava(jniEnv, j); }
using Boxed = NativeClientInterface;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/ClientInterface") };
const jmethodID method_getRecord { djinni::jniGetMethodID(clazz.get(), "getRecord", "(JLjava/lang/String;Ljava/lang/String;)Lcom/dropbox/djinni/test/ClientReturnedRecord;") };
~NativeClientInterface();
class JavaProxy final : djinni::JavaProxyCacheEntry, public ::ClientInterface {
static CppType toCpp(JNIEnv* jniEnv, JniType j) { return ::djinni::JniClass<NativeClientInterface>::get()._fromJava(jniEnv, j); }
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) { return {jniEnv, ::djinni::JniClass<NativeClientInterface>::get()._toJava(jniEnv, c)}; }
private:
NativeClientInterface();
friend ::djinni::JniClass<NativeClientInterface>;
friend ::djinni::JniInterface<::ClientInterface, NativeClientInterface>;
class JavaProxy final : ::djinni::JavaProxyCacheEntry, public ::ClientInterface
{
public:
JavaProxy(jobject obj);
virtual ::ClientReturnedRecord get_record(int64_t record_id, const std::string & utf8string, const std::experimental::optional<std::string> & misc) override;
JavaProxy(JniType j);
~JavaProxy();
::ClientReturnedRecord get_record(int64_t record_id, const std::string & utf8string, const std::experimental::optional<std::string> & misc) override;
private:
using djinni::JavaProxyCacheEntry::getGlobalRef;
friend class djinni::JniInterface<::ClientInterface, ::djinni_generated::NativeClientInterface>;
friend class djinni::JavaProxyCache<JavaProxy>;
using ::djinni::JavaProxyCacheEntry::getGlobalRef;
friend ::djinni::JniInterface<::ClientInterface, ::djinni_generated::NativeClientInterface>;
friend ::djinni::JavaProxyCache<JavaProxy>;
};
private:
NativeClientInterface();
friend class djinni::JniClass<::djinni_generated::NativeClientInterface>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/ClientInterface") };
const jmethodID method_getRecord { ::djinni::jniGetMethodID(clazz.get(), "getRecord", "(JLjava/lang/String;Ljava/lang/String;)Lcom/dropbox/djinni/test/ClientReturnedRecord;") };
};
} // namespace djinni_generated
......@@ -2,29 +2,30 @@
// This file generated by Djinni from client_interface.djinni
#include "NativeClientReturnedRecord.hpp" // my header
#include "HI64.hpp"
#include "HOptional.hpp"
#include "HString.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativeClientReturnedRecord::toJava(JNIEnv* jniEnv, ::ClientReturnedRecord c) {
jlong j_record_id = ::djinni::HI64::Unboxed::toJava(jniEnv, c.record_id);
djinni::LocalRef<jstring> j_content(jniEnv, ::djinni::HString::toJava(jniEnv, c.content));
djinni::LocalRef<jstring> j_misc(jniEnv, ::djinni::HOptional<std::experimental::optional, ::djinni::HString>::toJava(jniEnv, c.misc));
const auto & data = djinni::JniClass<::djinni_generated::NativeClientReturnedRecord>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_record_id, j_content.get(), j_misc.get());
djinni::jniExceptionCheck(jniEnv);
NativeClientReturnedRecord::NativeClientReturnedRecord() = default;
NativeClientReturnedRecord::~NativeClientReturnedRecord() = default;
auto NativeClientReturnedRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeClientReturnedRecord>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::I64::fromCpp(jniEnv, c.record_id),
::djinni::String::fromCpp(jniEnv, c.content).get(),
::djinni::Optional<std::experimental::optional, ::djinni::String>::fromCpp(jniEnv, c.misc).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::ClientReturnedRecord NativeClientReturnedRecord::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeClientReturnedRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeClientReturnedRecord>::get();
return ::ClientReturnedRecord(
::djinni::HI64::Unboxed::fromJava(jniEnv, jniEnv->GetLongField(j, data.field_mRecordId)),
::djinni::HString::fromJava(jniEnv, djinni::LocalRef<jstring>(jniEnv, static_cast<jstring>(jniEnv->GetObjectField(j, data.field_mContent))).get()),
::djinni::HOptional<std::experimental::optional, ::djinni::HString>::fromJava(jniEnv, djinni::LocalRef<jstring>(jniEnv, static_cast<jstring>(jniEnv->GetObjectField(j, data.field_mMisc))).get()));
const auto& data = ::djinni::JniClass<NativeClientReturnedRecord>::get();
return {::djinni::I64::toCpp(jniEnv, jniEnv->GetLongField(j, data.field_mRecordId)),
::djinni::String::toCpp(jniEnv, static_cast<jstring>(jniEnv->GetObjectField(j, data.field_mContent))),
::djinni::Optional<std::experimental::optional, ::djinni::String>::toCpp(jniEnv, static_cast<jstring>(jniEnv->GetObjectField(j, data.field_mMisc)))};
}
} // namespace djinni_generated
......@@ -13,18 +13,22 @@ public:
using CppType = ::ClientReturnedRecord;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::ClientReturnedRecord);
static ::ClientReturnedRecord fromJava(JNIEnv*, jobject);
using Boxed = NativeClientReturnedRecord;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/ClientReturnedRecord") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(JLjava/lang/String;Ljava/lang/String;)V") };
const jfieldID field_mRecordId { djinni::jniGetFieldID(clazz.get(), "mRecordId", "J") };
const jfieldID field_mContent { djinni::jniGetFieldID(clazz.get(), "mContent", "Ljava/lang/String;") };
const jfieldID field_mMisc { djinni::jniGetFieldID(clazz.get(), "mMisc", "Ljava/lang/String;") };
~NativeClientReturnedRecord();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeClientReturnedRecord() {}
friend class djinni::JniClass<::djinni_generated::NativeClientReturnedRecord>;
NativeClientReturnedRecord();
friend ::djinni::JniClass<NativeClientReturnedRecord>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/ClientReturnedRecord") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(JLjava/lang/String;Ljava/lang/String;)V") };
const jfieldID field_mRecordId { ::djinni::jniGetFieldID(clazz.get(), "mRecordId", "J") };
const jfieldID field_mContent { ::djinni::jniGetFieldID(clazz.get(), "mContent", "Ljava/lang/String;") };
const jfieldID field_mMisc { ::djinni::jniGetFieldID(clazz.get(), "mMisc", "Ljava/lang/String;") };
};
} // namespace djinni_generated
......@@ -8,17 +8,19 @@
namespace djinni_generated {
class NativeColor final : djinni::JniEnum {
class NativeColor final : ::djinni::JniEnum {
public:
using CppType = ::color;
using JniType = jobject;
static jobject toJava(JNIEnv* jniEnv, ::color c) { return djinni::JniClass<NativeColor>::get().create(jniEnv, static_cast<int>(c)).release(); }
static ::color fromJava(JNIEnv* jniEnv, jobject j) { return static_cast<::color>(djinni::JniClass<NativeColor>::get().ordinal(jniEnv, j)); }
using Boxed = NativeColor;
static CppType toCpp(JNIEnv* jniEnv, JniType j) { return static_cast<CppType>(::djinni::JniClass<NativeColor>::get().ordinal(jniEnv, j)); }
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, CppType c) { return ::djinni::JniClass<NativeColor>::get().create(jniEnv, static_cast<jint>(c)); }
private:
NativeColor() : JniEnum("com/dropbox/djinni/test/Color") {}
friend class djinni::JniClass<NativeColor>;
friend ::djinni::JniClass<NativeColor>;
};
} // namespace djinni_generated
......@@ -2,26 +2,28 @@
// This file generated by Djinni from constants.djinni
#include "NativeConstants.hpp" // my header
#include "HI32.hpp"
#include "HString.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativeConstants::toJava(JNIEnv* jniEnv, ::Constants c) {
jint j_some_integer = ::djinni::HI32::Unboxed::toJava(jniEnv, c.some_integer);
djinni::LocalRef<jstring> j_some_string(jniEnv, ::djinni::HString::toJava(jniEnv, c.some_string));
const auto & data = djinni::JniClass<::djinni_generated::NativeConstants>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_some_integer, j_some_string.get());
djinni::jniExceptionCheck(jniEnv);
NativeConstants::NativeConstants() = default;
NativeConstants::~NativeConstants() = default;
auto NativeConstants::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeConstants>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::I32::fromCpp(jniEnv, c.some_integer),
::djinni::String::fromCpp(jniEnv, c.some_string).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::Constants NativeConstants::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeConstants::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeConstants>::get();
return ::Constants(
::djinni::HI32::Unboxed::fromJava(jniEnv, jniEnv->GetIntField(j, data.field_mSomeInteger)),
::djinni::HString::fromJava(jniEnv, djinni::LocalRef<jstring>(jniEnv, static_cast<jstring>(jniEnv->GetObjectField(j, data.field_mSomeString))).get()));
const auto& data = ::djinni::JniClass<NativeConstants>::get();
return {::djinni::I32::toCpp(jniEnv, jniEnv->GetIntField(j, data.field_mSomeInteger)),
::djinni::String::toCpp(jniEnv, static_cast<jstring>(jniEnv->GetObjectField(j, data.field_mSomeString)))};
}
} // namespace djinni_generated
......@@ -13,17 +13,21 @@ public:
using CppType = ::Constants;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::Constants);
static ::Constants fromJava(JNIEnv*, jobject);
using Boxed = NativeConstants;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/Constants") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V") };
const jfieldID field_mSomeInteger { djinni::jniGetFieldID(clazz.get(), "mSomeInteger", "I") };
const jfieldID field_mSomeString { djinni::jniGetFieldID(clazz.get(), "mSomeString", "Ljava/lang/String;") };
~NativeConstants();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeConstants() {}
friend class djinni::JniClass<::djinni_generated::NativeConstants>;
NativeConstants();
friend ::djinni::JniClass<NativeConstants>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/Constants") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V") };
const jfieldID field_mSomeInteger { ::djinni::jniGetFieldID(clazz.get(), "mSomeInteger", "I") };
const jfieldID field_mSomeString { ::djinni::jniGetFieldID(clazz.get(), "mSomeString", "Ljava/lang/String;") };
};
} // namespace djinni_generated
......@@ -2,14 +2,15 @@
// This file generated by Djinni from exception.djinni
#include "NativeCppException.hpp" // my header
#include "HI32.hpp"
#include "Marshal.hpp"
#include "NativeCppException.hpp"
namespace djinni_generated {
NativeCppException::NativeCppException() : djinni::JniInterface<::CppException, NativeCppException>("com/dropbox/djinni/test/CppException$CppProxy") {}
NativeCppException::NativeCppException() : ::djinni::JniInterface<::CppException, NativeCppException>("com/dropbox/djinni/test/CppException$CppProxy") {}
NativeCppException::~NativeCppException() = default;
using namespace ::djinni_generated;
CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_CppException_00024CppProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef)
{
......@@ -23,11 +24,9 @@ CJNIEXPORT jint JNICALL Java_com_dropbox_djinni_test_CppException_00024CppProxy_
{
try {
DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef);
const std::shared_ptr<::CppException> & ref = djinni::CppProxyHandle<::CppException>::get(nativeRef);
int32_t cr = ref->throw_an_exception();
return ::djinni::HI32::Unboxed::toJava(jniEnv, cr);
const auto& ref = ::djinni::CppProxyHandle<::CppException>::get(nativeRef);
auto r = ref->throw_an_exception();
return ::djinni::I32::fromCpp(jniEnv, r);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -35,10 +34,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_CppException_get(JNIEnv*
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::shared_ptr<::CppException> cr = ::CppException::get();
return NativeCppException::toJava(jniEnv, cr);
auto r = ::CppException::get();
return ::djinni_generated::NativeCppException::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......
......@@ -8,18 +8,23 @@
namespace djinni_generated {
class NativeCppException final : djinni::JniInterface<::CppException, NativeCppException> {
class NativeCppException final : ::djinni::JniInterface<::CppException, NativeCppException> {
public:
using CppType = std::shared_ptr<::CppException>;
using JniType = jobject;
static jobject toJava(JNIEnv* jniEnv, std::shared_ptr<::CppException> c) { return djinni::JniClass<::djinni_generated::NativeCppException>::get()._toJava(jniEnv, c); }
static std::shared_ptr<::CppException> fromJava(JNIEnv* jniEnv, jobject j) { return djinni::JniClass<::djinni_generated::NativeCppException>::get()._fromJava(jniEnv, j); }
using Boxed = NativeCppException;
~NativeCppException();
static CppType toCpp(JNIEnv* jniEnv, JniType j) { return ::djinni::JniClass<NativeCppException>::get()._fromJava(jniEnv, j); }
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) { return {jniEnv, ::djinni::JniClass<NativeCppException>::get()._toJava(jniEnv, c)}; }
private:
NativeCppException();
friend class djinni::JniClass<::djinni_generated::NativeCppException>;
friend ::djinni::JniClass<NativeCppException>;
friend ::djinni::JniInterface<::CppException, NativeCppException>;
};
} // namespace djinni_generated
......@@ -2,23 +2,26 @@
// This file generated by Djinni from date.djinni
#include "NativeDateRecord.hpp" // my header
#include "HDate.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativeDateRecord::toJava(JNIEnv* jniEnv, ::DateRecord c) {
djinni::LocalRef<jobject> j_created_at(jniEnv, ::djinni::HDate::toJava(jniEnv, c.created_at));
const auto & data = djinni::JniClass<::djinni_generated::NativeDateRecord>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_created_at.get());
djinni::jniExceptionCheck(jniEnv);
NativeDateRecord::NativeDateRecord() = default;
NativeDateRecord::~NativeDateRecord() = default;
auto NativeDateRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeDateRecord>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::Date::fromCpp(jniEnv, c.created_at).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::DateRecord NativeDateRecord::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeDateRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeDateRecord>::get();
return ::DateRecord(
::djinni::HDate::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mCreatedAt)).get()));
const auto& data = ::djinni::JniClass<NativeDateRecord>::get();
return {::djinni::Date::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mCreatedAt))};
}
} // namespace djinni_generated
......@@ -13,16 +13,20 @@ public:
using CppType = ::DateRecord;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::DateRecord);
static ::DateRecord fromJava(JNIEnv*, jobject);
using Boxed = NativeDateRecord;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/DateRecord") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/Date;)V") };
const jfieldID field_mCreatedAt { djinni::jniGetFieldID(clazz.get(), "mCreatedAt", "Ljava/util/Date;") };
~NativeDateRecord();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeDateRecord() {}
friend class djinni::JniClass<::djinni_generated::NativeDateRecord>;
NativeDateRecord();
friend ::djinni::JniClass<NativeDateRecord>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/DateRecord") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/Date;)V") };
const jfieldID field_mCreatedAt { ::djinni::jniGetFieldID(clazz.get(), "mCreatedAt", "Ljava/util/Date;") };
};
} // namespace djinni_generated
......@@ -2,25 +2,26 @@
// This file generated by Djinni from date.djinni
#include "NativeMapDateRecord.hpp" // my header
#include "HDate.hpp"
#include "HMap.hpp"
#include "HString.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativeMapDateRecord::toJava(JNIEnv* jniEnv, ::MapDateRecord c) {
djinni::LocalRef<jobject> j_dates_by_id(jniEnv, ::djinni::HMap<::djinni::HString, ::djinni::HDate>::toJava(jniEnv, c.dates_by_id));
const auto & data = djinni::JniClass<::djinni_generated::NativeMapDateRecord>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_dates_by_id.get());
djinni::jniExceptionCheck(jniEnv);
NativeMapDateRecord::NativeMapDateRecord() = default;
NativeMapDateRecord::~NativeMapDateRecord() = default;
auto NativeMapDateRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeMapDateRecord>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::Map<::djinni::String, ::djinni::Date>::fromCpp(jniEnv, c.dates_by_id).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::MapDateRecord NativeMapDateRecord::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeMapDateRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeMapDateRecord>::get();
return ::MapDateRecord(
::djinni::HMap<::djinni::HString, ::djinni::HDate>::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mDatesById)).get()));
const auto& data = ::djinni::JniClass<NativeMapDateRecord>::get();
return {::djinni::Map<::djinni::String, ::djinni::Date>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mDatesById))};
}
} // namespace djinni_generated
......@@ -13,16 +13,20 @@ public:
using CppType = ::MapDateRecord;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::MapDateRecord);
static ::MapDateRecord fromJava(JNIEnv*, jobject);
using Boxed = NativeMapDateRecord;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/MapDateRecord") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/HashMap;)V") };
const jfieldID field_mDatesById { djinni::jniGetFieldID(clazz.get(), "mDatesById", "Ljava/util/HashMap;") };
~NativeMapDateRecord();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeMapDateRecord() {}
friend class djinni::JniClass<::djinni_generated::NativeMapDateRecord>;
NativeMapDateRecord();
friend ::djinni::JniClass<NativeMapDateRecord>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/MapDateRecord") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/HashMap;)V") };
const jfieldID field_mDatesById { ::djinni::jniGetFieldID(clazz.get(), "mDatesById", "Ljava/util/HashMap;") };
};
} // namespace djinni_generated
......@@ -2,26 +2,26 @@
// This file generated by Djinni from map.djinni
#include "NativeMapListRecord.hpp" // my header
#include "HI64.hpp"
#include "HList.hpp"
#include "HMap.hpp"
#include "HString.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativeMapListRecord::toJava(JNIEnv* jniEnv, ::MapListRecord c) {
djinni::LocalRef<jobject> j_map_list(jniEnv, ::djinni::HList<::djinni::HMap<::djinni::HString, ::djinni::HI64>>::toJava(jniEnv, c.map_list));
const auto & data = djinni::JniClass<::djinni_generated::NativeMapListRecord>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_map_list.get());
djinni::jniExceptionCheck(jniEnv);
NativeMapListRecord::NativeMapListRecord() = default;
NativeMapListRecord::~NativeMapListRecord() = default;
auto NativeMapListRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeMapListRecord>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::List<::djinni::Map<::djinni::String, ::djinni::I64>>::fromCpp(jniEnv, c.map_list).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::MapListRecord NativeMapListRecord::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeMapListRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeMapListRecord>::get();
return ::MapListRecord(
::djinni::HList<::djinni::HMap<::djinni::HString, ::djinni::HI64>>::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mMapList)).get()));
const auto& data = ::djinni::JniClass<NativeMapListRecord>::get();
return {::djinni::List<::djinni::Map<::djinni::String, ::djinni::I64>>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mMapList))};
}
} // namespace djinni_generated
......@@ -13,16 +13,20 @@ public:
using CppType = ::MapListRecord;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::MapListRecord);
static ::MapListRecord fromJava(JNIEnv*, jobject);
using Boxed = NativeMapListRecord;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/MapListRecord") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/ArrayList;)V") };
const jfieldID field_mMapList { djinni::jniGetFieldID(clazz.get(), "mMapList", "Ljava/util/ArrayList;") };
~NativeMapListRecord();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeMapListRecord() {}
friend class djinni::JniClass<::djinni_generated::NativeMapListRecord>;
NativeMapListRecord();
friend ::djinni::JniClass<NativeMapListRecord>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/MapListRecord") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/ArrayList;)V") };
const jfieldID field_mMapList { ::djinni::jniGetFieldID(clazz.get(), "mMapList", "Ljava/util/ArrayList;") };
};
} // namespace djinni_generated
......@@ -2,25 +2,26 @@
// This file generated by Djinni from map.djinni
#include "NativeMapRecord.hpp" // my header
#include "HI64.hpp"
#include "HMap.hpp"
#include "HString.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativeMapRecord::toJava(JNIEnv* jniEnv, ::MapRecord c) {
djinni::LocalRef<jobject> j_map(jniEnv, ::djinni::HMap<::djinni::HString, ::djinni::HI64>::toJava(jniEnv, c.map));
const auto & data = djinni::JniClass<::djinni_generated::NativeMapRecord>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_map.get());
djinni::jniExceptionCheck(jniEnv);
NativeMapRecord::NativeMapRecord() = default;
NativeMapRecord::~NativeMapRecord() = default;
auto NativeMapRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeMapRecord>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::Map<::djinni::String, ::djinni::I64>::fromCpp(jniEnv, c.map).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::MapRecord NativeMapRecord::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeMapRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeMapRecord>::get();
return ::MapRecord(
::djinni::HMap<::djinni::HString, ::djinni::HI64>::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mMap)).get()));
const auto& data = ::djinni::JniClass<NativeMapRecord>::get();
return {::djinni::Map<::djinni::String, ::djinni::I64>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mMap))};
}
} // namespace djinni_generated
......@@ -13,16 +13,20 @@ public:
using CppType = ::MapRecord;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::MapRecord);
static ::MapRecord fromJava(JNIEnv*, jobject);
using Boxed = NativeMapRecord;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/MapRecord") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/HashMap;)V") };
const jfieldID field_mMap { djinni::jniGetFieldID(clazz.get(), "mMap", "Ljava/util/HashMap;") };
~NativeMapRecord();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeMapRecord() {}
friend class djinni::JniClass<::djinni_generated::NativeMapRecord>;
NativeMapRecord();
friend ::djinni::JniClass<NativeMapRecord>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/MapRecord") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/HashMap;)V") };
const jfieldID field_mMap { ::djinni::jniGetFieldID(clazz.get(), "mMap", "Ljava/util/HashMap;") };
};
} // namespace djinni_generated
......@@ -2,25 +2,26 @@
// This file generated by Djinni from nested_collection.djinni
#include "NativeNestedCollection.hpp" // my header
#include "HList.hpp"
#include "HSet.hpp"
#include "HString.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativeNestedCollection::toJava(JNIEnv* jniEnv, ::NestedCollection c) {
djinni::LocalRef<jobject> j_set_list(jniEnv, ::djinni::HList<::djinni::HSet<::djinni::HString>>::toJava(jniEnv, c.set_list));
const auto & data = djinni::JniClass<::djinni_generated::NativeNestedCollection>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_set_list.get());
djinni::jniExceptionCheck(jniEnv);
NativeNestedCollection::NativeNestedCollection() = default;
NativeNestedCollection::~NativeNestedCollection() = default;
auto NativeNestedCollection::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeNestedCollection>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::List<::djinni::Set<::djinni::String>>::fromCpp(jniEnv, c.set_list).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::NestedCollection NativeNestedCollection::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeNestedCollection::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeNestedCollection>::get();
return ::NestedCollection(
::djinni::HList<::djinni::HSet<::djinni::HString>>::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mSetList)).get()));
const auto& data = ::djinni::JniClass<NativeNestedCollection>::get();
return {::djinni::List<::djinni::Set<::djinni::String>>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mSetList))};
}
} // namespace djinni_generated
......@@ -13,16 +13,20 @@ public:
using CppType = ::NestedCollection;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::NestedCollection);
static ::NestedCollection fromJava(JNIEnv*, jobject);
using Boxed = NativeNestedCollection;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/NestedCollection") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/ArrayList;)V") };
const jfieldID field_mSetList { djinni::jniGetFieldID(clazz.get(), "mSetList", "Ljava/util/ArrayList;") };
~NativeNestedCollection();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeNestedCollection() {}
friend class djinni::JniClass<::djinni_generated::NativeNestedCollection>;
NativeNestedCollection();
friend ::djinni::JniClass<NativeNestedCollection>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/NestedCollection") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/ArrayList;)V") };
const jfieldID field_mSetList { ::djinni::jniGetFieldID(clazz.get(), "mSetList", "Ljava/util/ArrayList;") };
};
} // namespace djinni_generated
......@@ -2,24 +2,26 @@
// This file generated by Djinni from primitive_list.djinni
#include "NativePrimitiveList.hpp" // my header
#include "HI64.hpp"
#include "HList.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativePrimitiveList::toJava(JNIEnv* jniEnv, ::PrimitiveList c) {
djinni::LocalRef<jobject> j_list(jniEnv, ::djinni::HList<::djinni::HI64>::toJava(jniEnv, c.list));
const auto & data = djinni::JniClass<::djinni_generated::NativePrimitiveList>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_list.get());
djinni::jniExceptionCheck(jniEnv);
NativePrimitiveList::NativePrimitiveList() = default;
NativePrimitiveList::~NativePrimitiveList() = default;
auto NativePrimitiveList::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativePrimitiveList>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::List<::djinni::I64>::fromCpp(jniEnv, c.list).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::PrimitiveList NativePrimitiveList::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativePrimitiveList::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativePrimitiveList>::get();
return ::PrimitiveList(
::djinni::HList<::djinni::HI64>::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mList)).get()));
const auto& data = ::djinni::JniClass<NativePrimitiveList>::get();
return {::djinni::List<::djinni::I64>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mList))};
}
} // namespace djinni_generated
......@@ -13,16 +13,20 @@ public:
using CppType = ::PrimitiveList;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::PrimitiveList);
static ::PrimitiveList fromJava(JNIEnv*, jobject);
using Boxed = NativePrimitiveList;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/PrimitiveList") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/ArrayList;)V") };
const jfieldID field_mList { djinni::jniGetFieldID(clazz.get(), "mList", "Ljava/util/ArrayList;") };
~NativePrimitiveList();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativePrimitiveList() {}
friend class djinni::JniClass<::djinni_generated::NativePrimitiveList>;
NativePrimitiveList();
friend ::djinni::JniClass<NativePrimitiveList>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/PrimitiveList") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/ArrayList;)V") };
const jfieldID field_mList { ::djinni::jniGetFieldID(clazz.get(), "mList", "Ljava/util/ArrayList;") };
};
} // namespace djinni_generated
......@@ -2,26 +2,28 @@
// This file generated by Djinni from derivings.djinni
#include "NativeRecordWithDerivings.hpp" // my header
#include "HI32.hpp"
#include "HString.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativeRecordWithDerivings::toJava(JNIEnv* jniEnv, ::RecordWithDerivings c) {
jint j_key1 = ::djinni::HI32::Unboxed::toJava(jniEnv, c.key1);
djinni::LocalRef<jstring> j_key2(jniEnv, ::djinni::HString::toJava(jniEnv, c.key2));
const auto & data = djinni::JniClass<::djinni_generated::NativeRecordWithDerivings>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_key1, j_key2.get());
djinni::jniExceptionCheck(jniEnv);
NativeRecordWithDerivings::NativeRecordWithDerivings() = default;
NativeRecordWithDerivings::~NativeRecordWithDerivings() = default;
auto NativeRecordWithDerivings::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeRecordWithDerivings>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::I32::fromCpp(jniEnv, c.key1),
::djinni::String::fromCpp(jniEnv, c.key2).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::RecordWithDerivings NativeRecordWithDerivings::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeRecordWithDerivings::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeRecordWithDerivings>::get();
return ::RecordWithDerivings(
::djinni::HI32::Unboxed::fromJava(jniEnv, jniEnv->GetIntField(j, data.field_mKey1)),
::djinni::HString::fromJava(jniEnv, djinni::LocalRef<jstring>(jniEnv, static_cast<jstring>(jniEnv->GetObjectField(j, data.field_mKey2))).get()));
const auto& data = ::djinni::JniClass<NativeRecordWithDerivings>::get();
return {::djinni::I32::toCpp(jniEnv, jniEnv->GetIntField(j, data.field_mKey1)),
::djinni::String::toCpp(jniEnv, static_cast<jstring>(jniEnv->GetObjectField(j, data.field_mKey2)))};
}
} // namespace djinni_generated
......@@ -13,17 +13,21 @@ public:
using CppType = ::RecordWithDerivings;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::RecordWithDerivings);
static ::RecordWithDerivings fromJava(JNIEnv*, jobject);
using Boxed = NativeRecordWithDerivings;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/RecordWithDerivings") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V") };
const jfieldID field_mKey1 { djinni::jniGetFieldID(clazz.get(), "mKey1", "I") };
const jfieldID field_mKey2 { djinni::jniGetFieldID(clazz.get(), "mKey2", "Ljava/lang/String;") };
~NativeRecordWithDerivings();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeRecordWithDerivings() {}
friend class djinni::JniClass<::djinni_generated::NativeRecordWithDerivings>;
NativeRecordWithDerivings();
friend ::djinni::JniClass<NativeRecordWithDerivings>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/RecordWithDerivings") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V") };
const jfieldID field_mKey1 { ::djinni::jniGetFieldID(clazz.get(), "mKey1", "I") };
const jfieldID field_mKey2 { ::djinni::jniGetFieldID(clazz.get(), "mKey2", "Ljava/lang/String;") };
};
} // namespace djinni_generated
......@@ -2,26 +2,29 @@
// This file generated by Djinni from derivings.djinni
#include "NativeRecordWithNestedDerivings.hpp" // my header
#include "HI32.hpp"
#include "Marshal.hpp"
#include "NativeRecordWithDerivings.hpp"
namespace djinni_generated {
jobject NativeRecordWithNestedDerivings::toJava(JNIEnv* jniEnv, ::RecordWithNestedDerivings c) {
jint j_key = ::djinni::HI32::Unboxed::toJava(jniEnv, c.key);
djinni::LocalRef<jobject> j_rec(jniEnv, NativeRecordWithDerivings::toJava(jniEnv, c.rec));
const auto & data = djinni::JniClass<::djinni_generated::NativeRecordWithNestedDerivings>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_key, j_rec.get());
djinni::jniExceptionCheck(jniEnv);
NativeRecordWithNestedDerivings::NativeRecordWithNestedDerivings() = default;
NativeRecordWithNestedDerivings::~NativeRecordWithNestedDerivings() = default;
auto NativeRecordWithNestedDerivings::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeRecordWithNestedDerivings>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::I32::fromCpp(jniEnv, c.key),
::djinni_generated::NativeRecordWithDerivings::fromCpp(jniEnv, c.rec).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::RecordWithNestedDerivings NativeRecordWithNestedDerivings::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeRecordWithNestedDerivings::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeRecordWithNestedDerivings>::get();
return ::RecordWithNestedDerivings(
::djinni::HI32::Unboxed::fromJava(jniEnv, jniEnv->GetIntField(j, data.field_mKey)),
NativeRecordWithDerivings::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mRec)).get()));
const auto& data = ::djinni::JniClass<NativeRecordWithNestedDerivings>::get();
return {::djinni::I32::toCpp(jniEnv, jniEnv->GetIntField(j, data.field_mKey)),
::djinni_generated::NativeRecordWithDerivings::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mRec))};
}
} // namespace djinni_generated
......@@ -13,17 +13,21 @@ public:
using CppType = ::RecordWithNestedDerivings;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::RecordWithNestedDerivings);
static ::RecordWithNestedDerivings fromJava(JNIEnv*, jobject);
using Boxed = NativeRecordWithNestedDerivings;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/RecordWithNestedDerivings") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(ILcom/dropbox/djinni/test/RecordWithDerivings;)V") };
const jfieldID field_mKey { djinni::jniGetFieldID(clazz.get(), "mKey", "I") };
const jfieldID field_mRec { djinni::jniGetFieldID(clazz.get(), "mRec", "Lcom/dropbox/djinni/test/RecordWithDerivings;") };
~NativeRecordWithNestedDerivings();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeRecordWithNestedDerivings() {}
friend class djinni::JniClass<::djinni_generated::NativeRecordWithNestedDerivings>;
NativeRecordWithNestedDerivings();
friend ::djinni::JniClass<NativeRecordWithNestedDerivings>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/RecordWithNestedDerivings") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(ILcom/dropbox/djinni/test/RecordWithDerivings;)V") };
const jfieldID field_mKey { ::djinni::jniGetFieldID(clazz.get(), "mKey", "I") };
const jfieldID field_mRec { ::djinni::jniGetFieldID(clazz.get(), "mRec", "Lcom/dropbox/djinni/test/RecordWithDerivings;") };
};
} // namespace djinni_generated
......@@ -2,24 +2,26 @@
// This file generated by Djinni from set.djinni
#include "NativeSetRecord.hpp" // my header
#include "HSet.hpp"
#include "HString.hpp"
#include "Marshal.hpp"
namespace djinni_generated {
jobject NativeSetRecord::toJava(JNIEnv* jniEnv, ::SetRecord c) {
djinni::LocalRef<jobject> j_set(jniEnv, ::djinni::HSet<::djinni::HString>::toJava(jniEnv, c.set));
const auto & data = djinni::JniClass<::djinni_generated::NativeSetRecord>::get();
jobject r = jniEnv->NewObject(data.clazz.get(), data.jconstructor, j_set.get());
djinni::jniExceptionCheck(jniEnv);
NativeSetRecord::NativeSetRecord() = default;
NativeSetRecord::~NativeSetRecord() = default;
auto NativeSetRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeSetRecord>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::Set<::djinni::String>::fromCpp(jniEnv, c.set).get())};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
::SetRecord NativeSetRecord::fromJava(JNIEnv* jniEnv, jobject j) {
auto NativeSetRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
assert(j != nullptr);
const auto & data = djinni::JniClass<::djinni_generated::NativeSetRecord>::get();
return ::SetRecord(
::djinni::HSet<::djinni::HString>::fromJava(jniEnv, djinni::LocalRef<jobject>(jniEnv, jniEnv->GetObjectField(j, data.field_mSet)).get()));
const auto& data = ::djinni::JniClass<NativeSetRecord>::get();
return {::djinni::Set<::djinni::String>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mSet))};
}
} // namespace djinni_generated
......@@ -13,16 +13,20 @@ public:
using CppType = ::SetRecord;
using JniType = jobject;
static jobject toJava(JNIEnv*, ::SetRecord);
static ::SetRecord fromJava(JNIEnv*, jobject);
using Boxed = NativeSetRecord;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/SetRecord") };
const jmethodID jconstructor { djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/HashSet;)V") };
const jfieldID field_mSet { djinni::jniGetFieldID(clazz.get(), "mSet", "Ljava/util/HashSet;") };
~NativeSetRecord();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeSetRecord() {}
friend class djinni::JniClass<::djinni_generated::NativeSetRecord>;
NativeSetRecord();
friend ::djinni::JniClass<NativeSetRecord>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/SetRecord") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(Ljava/util/HashSet;)V") };
const jfieldID field_mSet { ::djinni::jniGetFieldID(clazz.get(), "mSet", "Ljava/util/HashSet;") };
};
} // namespace djinni_generated
......@@ -2,12 +2,7 @@
// This file generated by Djinni from test.djinni
#include "NativeTestHelpers.hpp" // my header
#include "HBool.hpp"
#include "HI32.hpp"
#include "HI64.hpp"
#include "HMap.hpp"
#include "HOptional.hpp"
#include "HString.hpp"
#include "Marshal.hpp"
#include "NativeAssortedIntegers.hpp"
#include "NativeClientInterface.hpp"
#include "NativeColor.hpp"
......@@ -19,9 +14,10 @@
namespace djinni_generated {
NativeTestHelpers::NativeTestHelpers() : djinni::JniInterface<::TestHelpers, NativeTestHelpers>("com/dropbox/djinni/test/TestHelpers$CppProxy") {}
NativeTestHelpers::NativeTestHelpers() : ::djinni::JniInterface<::TestHelpers, NativeTestHelpers>("com/dropbox/djinni/test/TestHelpers$CppProxy") {}
NativeTestHelpers::~NativeTestHelpers() = default;
using namespace ::djinni_generated;
CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_00024CppProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef)
{
......@@ -35,10 +31,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_getSetRecord
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
::SetRecord cr = ::TestHelpers::get_set_record();
return NativeSetRecord::toJava(jniEnv, cr);
auto r = ::TestHelpers::get_set_record();
return ::djinni_generated::NativeSetRecord::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -46,11 +40,8 @@ CJNIEXPORT jboolean JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkSetRec
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
::SetRecord c_rec = NativeSetRecord::fromJava(jniEnv, j_rec);
bool cr = ::TestHelpers::check_set_record(c_rec);
return ::djinni::HBool::Unboxed::toJava(jniEnv, cr);
auto r = ::TestHelpers::check_set_record(::djinni_generated::NativeSetRecord::toCpp(jniEnv, j_rec));
return ::djinni::Bool::fromCpp(jniEnv, r);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -58,10 +49,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_getPrimitive
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
::PrimitiveList cr = ::TestHelpers::get_primitive_list();
return NativePrimitiveList::toJava(jniEnv, cr);
auto r = ::TestHelpers::get_primitive_list();
return ::djinni_generated::NativePrimitiveList::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -69,11 +58,8 @@ CJNIEXPORT jboolean JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkPrimit
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
::PrimitiveList c_pl = NativePrimitiveList::fromJava(jniEnv, j_pl);
bool cr = ::TestHelpers::check_primitive_list(c_pl);
return ::djinni::HBool::Unboxed::toJava(jniEnv, cr);
auto r = ::TestHelpers::check_primitive_list(::djinni_generated::NativePrimitiveList::toCpp(jniEnv, j_pl));
return ::djinni::Bool::fromCpp(jniEnv, r);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -81,10 +67,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_getNestedCol
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
::NestedCollection cr = ::TestHelpers::get_nested_collection();
return NativeNestedCollection::toJava(jniEnv, cr);
auto r = ::TestHelpers::get_nested_collection();
return ::djinni_generated::NativeNestedCollection::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -92,11 +76,8 @@ CJNIEXPORT jboolean JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkNested
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
::NestedCollection c_nc = NativeNestedCollection::fromJava(jniEnv, j_nc);
bool cr = ::TestHelpers::check_nested_collection(c_nc);
return ::djinni::HBool::Unboxed::toJava(jniEnv, cr);
auto r = ::TestHelpers::check_nested_collection(::djinni_generated::NativeNestedCollection::toCpp(jniEnv, j_nc));
return ::djinni::Bool::fromCpp(jniEnv, r);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -104,10 +85,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_getMap(JNIEn
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::unordered_map<std::string, int64_t> cr = ::TestHelpers::get_map();
return ::djinni::HMap<::djinni::HString, ::djinni::HI64>::toJava(jniEnv, cr);
auto r = ::TestHelpers::get_map();
return ::djinni::Map<::djinni::String, ::djinni::I64>::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -115,11 +94,8 @@ CJNIEXPORT jboolean JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkMap(JN
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::unordered_map<std::string, int64_t> c_m = ::djinni::HMap<::djinni::HString, ::djinni::HI64>::fromJava(jniEnv, j_m);
bool cr = ::TestHelpers::check_map(c_m);
return ::djinni::HBool::Unboxed::toJava(jniEnv, cr);
auto r = ::TestHelpers::check_map(::djinni::Map<::djinni::String, ::djinni::I64>::toCpp(jniEnv, j_m));
return ::djinni::Bool::fromCpp(jniEnv, r);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -127,10 +103,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_getEmptyMap(
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::unordered_map<std::string, int64_t> cr = ::TestHelpers::get_empty_map();
return ::djinni::HMap<::djinni::HString, ::djinni::HI64>::toJava(jniEnv, cr);
auto r = ::TestHelpers::get_empty_map();
return ::djinni::Map<::djinni::String, ::djinni::I64>::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -138,11 +112,8 @@ CJNIEXPORT jboolean JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkEmptyM
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::unordered_map<std::string, int64_t> c_m = ::djinni::HMap<::djinni::HString, ::djinni::HI64>::fromJava(jniEnv, j_m);
bool cr = ::TestHelpers::check_empty_map(c_m);
return ::djinni::HBool::Unboxed::toJava(jniEnv, cr);
auto r = ::TestHelpers::check_empty_map(::djinni::Map<::djinni::String, ::djinni::I64>::toCpp(jniEnv, j_m));
return ::djinni::Bool::fromCpp(jniEnv, r);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -150,10 +121,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_getMapListRe
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
::MapListRecord cr = ::TestHelpers::get_map_list_record();
return NativeMapListRecord::toJava(jniEnv, cr);
auto r = ::TestHelpers::get_map_list_record();
return ::djinni_generated::NativeMapListRecord::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -161,11 +130,8 @@ CJNIEXPORT jboolean JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkMapLis
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
::MapListRecord c_m = NativeMapListRecord::fromJava(jniEnv, j_m);
bool cr = ::TestHelpers::check_map_list_record(c_m);
return ::djinni::HBool::Unboxed::toJava(jniEnv, cr);
auto r = ::TestHelpers::check_map_list_record(::djinni_generated::NativeMapListRecord::toCpp(jniEnv, j_m));
return ::djinni::Bool::fromCpp(jniEnv, r);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -173,9 +139,7 @@ CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkClientInte
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::shared_ptr<::ClientInterface> c_i = NativeClientInterface::fromJava(jniEnv, j_i);
::TestHelpers::check_client_interface_ascii(c_i);
::TestHelpers::check_client_interface_ascii(::djinni_generated::NativeClientInterface::toCpp(jniEnv, j_i));
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
}
......@@ -183,9 +147,7 @@ CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkClientInte
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::shared_ptr<::ClientInterface> c_i = NativeClientInterface::fromJava(jniEnv, j_i);
::TestHelpers::check_client_interface_nonascii(c_i);
::TestHelpers::check_client_interface_nonascii(::djinni_generated::NativeClientInterface::toCpp(jniEnv, j_i));
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
}
......@@ -193,9 +155,7 @@ CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkEnumMap(JN
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::unordered_map<::color, std::string> c_m = ::djinni::HMap<NativeColor, ::djinni::HString>::fromJava(jniEnv, j_m);
::TestHelpers::check_enum_map(c_m);
::TestHelpers::check_enum_map(::djinni::Map<::djinni_generated::NativeColor, ::djinni::String>::toCpp(jniEnv, j_m));
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
}
......@@ -203,9 +163,7 @@ CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkEnum(JNIEn
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
::color c_c = NativeColor::fromJava(jniEnv, j_c);
::TestHelpers::check_enum(c_c);
::TestHelpers::check_enum(::djinni_generated::NativeColor::toCpp(jniEnv, j_c));
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
}
......@@ -213,11 +171,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_tokenId(JNIE
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::shared_ptr<::Token> c_t = NativeToken::fromJava(jniEnv, j_t);
std::shared_ptr<::Token> cr = ::TestHelpers::token_id(c_t);
return NativeToken::toJava(jniEnv, cr);
auto r = ::TestHelpers::token_id(::djinni_generated::NativeToken::toCpp(jniEnv, j_t));
return ::djinni_generated::NativeToken::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -225,10 +180,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_createCppTok
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::shared_ptr<::Token> cr = ::TestHelpers::create_cpp_token();
return NativeToken::toJava(jniEnv, cr);
auto r = ::TestHelpers::create_cpp_token();
return ::djinni_generated::NativeToken::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -236,9 +189,7 @@ CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkCppToken(J
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::shared_ptr<::Token> c_t = NativeToken::fromJava(jniEnv, j_t);
::TestHelpers::check_cpp_token(c_t);
::TestHelpers::check_cpp_token(::djinni_generated::NativeToken::toCpp(jniEnv, j_t));
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
}
......@@ -246,11 +197,8 @@ CJNIEXPORT jlong JNICALL Java_com_dropbox_djinni_test_TestHelpers_cppTokenId(JNI
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::shared_ptr<::Token> c_t = NativeToken::fromJava(jniEnv, j_t);
int64_t cr = ::TestHelpers::cpp_token_id(c_t);
return ::djinni::HI64::Unboxed::toJava(jniEnv, cr);
auto r = ::TestHelpers::cpp_token_id(::djinni_generated::NativeToken::toCpp(jniEnv, j_t));
return ::djinni::I64::fromCpp(jniEnv, r);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -258,10 +206,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_returnNone(J
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::experimental::optional<int32_t> cr = ::TestHelpers::return_none();
return ::djinni::HOptional<std::experimental::optional, ::djinni::HI32>::toJava(jniEnv, cr);
auto r = ::TestHelpers::return_none();
return ::djinni::Optional<std::experimental::optional, ::djinni::I32>::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......@@ -269,11 +215,8 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_assortedInte
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
::AssortedIntegers c_i = NativeAssortedIntegers::fromJava(jniEnv, j_i);
::AssortedIntegers cr = ::TestHelpers::assorted_integers_id(c_i);
return NativeAssortedIntegers::toJava(jniEnv, cr);
auto r = ::TestHelpers::assorted_integers_id(::djinni_generated::NativeAssortedIntegers::toCpp(jniEnv, j_i));
return ::djinni_generated::NativeAssortedIntegers::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
......
......@@ -8,18 +8,23 @@
namespace djinni_generated {
class NativeTestHelpers final : djinni::JniInterface<::TestHelpers, NativeTestHelpers> {
class NativeTestHelpers final : ::djinni::JniInterface<::TestHelpers, NativeTestHelpers> {
public:
using CppType = std::shared_ptr<::TestHelpers>;
using JniType = jobject;
static jobject toJava(JNIEnv* jniEnv, std::shared_ptr<::TestHelpers> c) { return djinni::JniClass<::djinni_generated::NativeTestHelpers>::get()._toJava(jniEnv, c); }
static std::shared_ptr<::TestHelpers> fromJava(JNIEnv* jniEnv, jobject j) { return djinni::JniClass<::djinni_generated::NativeTestHelpers>::get()._fromJava(jniEnv, j); }
using Boxed = NativeTestHelpers;
~NativeTestHelpers();
static CppType toCpp(JNIEnv* jniEnv, JniType j) { return ::djinni::JniClass<NativeTestHelpers>::get()._fromJava(jniEnv, j); }
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) { return {jniEnv, ::djinni::JniClass<NativeTestHelpers>::get()._toJava(jniEnv, c)}; }
private:
NativeTestHelpers();
friend class djinni::JniClass<::djinni_generated::NativeTestHelpers>;
friend ::djinni::JniClass<NativeTestHelpers>;
friend ::djinni::JniInterface<::TestHelpers, NativeTestHelpers>;
};
} // namespace djinni_generated
......@@ -5,10 +5,14 @@
namespace djinni_generated {
NativeToken::NativeToken() : djinni::JniInterface<::Token, NativeToken>("com/dropbox/djinni/test/Token$CppProxy") {}
NativeToken::NativeToken() : ::djinni::JniInterface<::Token, NativeToken>("com/dropbox/djinni/test/Token$CppProxy") {}
NativeToken::~NativeToken() = default;
NativeToken::JavaProxy::JavaProxy(JniType j) : JavaProxyCacheEntry(j) { }
NativeToken::JavaProxy::~JavaProxy() = default;
NativeToken::JavaProxy::JavaProxy(jobject obj) : JavaProxyCacheEntry(obj) {}
using namespace ::djinni_generated;
CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_Token_00024CppProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef)
{
......
......@@ -8,29 +8,37 @@
namespace djinni_generated {
class NativeToken final : djinni::JniInterface<::Token, NativeToken> {
class NativeToken final : ::djinni::JniInterface<::Token, NativeToken> {
public:
using CppType = std::shared_ptr<::Token>;
using JniType = jobject;
static jobject toJava(JNIEnv* jniEnv, std::shared_ptr<::Token> c) { return djinni::JniClass<::djinni_generated::NativeToken>::get()._toJava(jniEnv, c); }
static std::shared_ptr<::Token> fromJava(JNIEnv* jniEnv, jobject j) { return djinni::JniClass<::djinni_generated::NativeToken>::get()._fromJava(jniEnv, j); }
using Boxed = NativeToken;
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/Token") };
~NativeToken();
class JavaProxy final : djinni::JavaProxyCacheEntry, public ::Token {
static CppType toCpp(JNIEnv* jniEnv, JniType j) { return ::djinni::JniClass<NativeToken>::get()._fromJava(jniEnv, j); }
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) { return {jniEnv, ::djinni::JniClass<NativeToken>::get()._toJava(jniEnv, c)}; }
private:
NativeToken();
friend ::djinni::JniClass<NativeToken>;
friend ::djinni::JniInterface<::Token, NativeToken>;
class JavaProxy final : ::djinni::JavaProxyCacheEntry, public ::Token
{
public:
JavaProxy(jobject obj);
JavaProxy(JniType j);
~JavaProxy();
private:
using djinni::JavaProxyCacheEntry::getGlobalRef;
friend class djinni::JniInterface<::Token, ::djinni_generated::NativeToken>;
friend class djinni::JavaProxyCache<JavaProxy>;
using ::djinni::JavaProxyCacheEntry::getGlobalRef;
friend ::djinni::JniInterface<::Token, ::djinni_generated::NativeToken>;
friend ::djinni::JavaProxyCache<JavaProxy>;
};
private:
NativeToken();
friend class djinni::JniClass<::djinni_generated::NativeToken>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/Token") };
};
} // namespace djinni_generated
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment