Commit b08c54a0 authored by Jacob Potter's avatar Jacob Potter

Fix JNI proxy infrastructure

We previously had weak-maps for passing objects from Java to C++ (necessary for listeners etc),
but each C++->Java pass would previously create a new proxy. This change:

- Unifies the +c and +j wrapper types, allowing an interface to be +c +j
- Fixes C++->Java object passing to use the existing wrapper if one exists
- Fixes both C++->Java and Java->C++ to "unwrap" an object if need be (allowing a Java object to be passed to C++ and then back properly)
- Adds tests for all of the above
parent a0997b01
...@@ -10,12 +10,12 @@ public abstract class SortItems { ...@@ -10,12 +10,12 @@ public abstract class SortItems {
public static native SortItems createWithListener(TextboxListener listener); public static native SortItems createWithListener(TextboxListener listener);
public static final class NativeProxy extends SortItems public static final class CppProxy extends SortItems
{ {
private final long nativeRef; private final long nativeRef;
private final AtomicBoolean destroyed = new AtomicBoolean(false); private final AtomicBoolean destroyed = new AtomicBoolean(false);
private NativeProxy(long nativeRef) private CppProxy(long nativeRef)
{ {
if (nativeRef == 0) throw new RuntimeException("nativeRef is zero"); if (nativeRef == 0) throw new RuntimeException("nativeRef is zero");
this.nativeRef = nativeRef; this.nativeRef = nativeRef;
......
...@@ -8,23 +8,23 @@ ...@@ -8,23 +8,23 @@
namespace djinni_generated { namespace djinni_generated {
NativeSortItems::NativeSortItems() : djinni::JniInterfaceCppExt<::textsort::SortItems>("com/dropbox/textsort/SortItems$NativeProxy") {} NativeSortItems::NativeSortItems() : djinni::JniInterface<::textsort::SortItems, NativeSortItems>("com/dropbox/textsort/SortItems$CppProxy") {}
using namespace ::djinni_generated; using namespace ::djinni_generated;
CJNIEXPORT void JNICALL Java_com_dropbox_textsort_SortItems_00024NativeProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef) CJNIEXPORT void JNICALL Java_com_dropbox_textsort_SortItems_00024CppProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef)
{ {
try { try {
DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef); DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef);
delete reinterpret_cast<std::shared_ptr<::textsort::SortItems>*>(nativeRef); delete reinterpret_cast<djinni::CppProxyHandle<::textsort::SortItems>*>(nativeRef);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, ) } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
} }
CJNIEXPORT void JNICALL Java_com_dropbox_textsort_SortItems_00024NativeProxy_native_1sort(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef, jobject j_items) CJNIEXPORT void JNICALL Java_com_dropbox_textsort_SortItems_00024CppProxy_native_1sort(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef, jobject j_items)
{ {
try { try {
DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef); DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef);
const std::shared_ptr<::textsort::SortItems> & ref = *reinterpret_cast<const std::shared_ptr<::textsort::SortItems>*>(nativeRef); const std::shared_ptr<::textsort::SortItems> & ref = djinni::CppProxyHandle<::textsort::SortItems>::get(nativeRef);
::textsort::ItemList c_items = NativeItemList::fromJava(jniEnv, j_items); ::textsort::ItemList c_items = NativeItemList::fromJava(jniEnv, j_items);
ref->sort(c_items); ref->sort(c_items);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
namespace djinni_generated { namespace djinni_generated {
class NativeSortItems final : djinni::JniInterfaceCppExt<::textsort::SortItems> { class NativeSortItems final : djinni::JniInterface<::textsort::SortItems, NativeSortItems> {
public: public:
using CppType = std::shared_ptr<::textsort::SortItems>; using CppType = std::shared_ptr<::textsort::SortItems>;
using JniType = jobject; using JniType = jobject;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
namespace djinni_generated { namespace djinni_generated {
NativeTextboxListener::NativeTextboxListener() : djinni::JniInterfaceJavaExt<::textsort::TextboxListener, NativeTextboxListener>() {} NativeTextboxListener::NativeTextboxListener() : djinni::JniInterface<::textsort::TextboxListener, NativeTextboxListener>() {}
NativeTextboxListener::JavaProxy::JavaProxy(jobject obj) : JavaProxyCacheEntry(obj) {} NativeTextboxListener::JavaProxy::JavaProxy(jobject obj) : JavaProxyCacheEntry(obj) {}
......
...@@ -8,11 +8,12 @@ ...@@ -8,11 +8,12 @@
namespace djinni_generated { namespace djinni_generated {
class NativeTextboxListener final : djinni::JniInterfaceJavaExt<::textsort::TextboxListener, NativeTextboxListener> { class NativeTextboxListener final : djinni::JniInterface<::textsort::TextboxListener, NativeTextboxListener> {
public: public:
using CppType = std::shared_ptr<::textsort::TextboxListener>; using CppType = std::shared_ptr<::textsort::TextboxListener>;
using JniType = jobject; 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); } static std::shared_ptr<::textsort::TextboxListener> fromJava(JNIEnv* jniEnv, jobject j) { return djinni::JniClass<::djinni_generated::NativeTextboxListener>::get()._fromJava(jniEnv, j); }
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/textsort/TextboxListener") }; const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/textsort/TextboxListener") };
...@@ -25,7 +26,7 @@ public: ...@@ -25,7 +26,7 @@ public:
private: private:
using djinni::JavaProxyCacheEntry::getGlobalRef; using djinni::JavaProxyCacheEntry::getGlobalRef;
friend class djinni::JniInterfaceJavaExt<::textsort::TextboxListener, ::djinni_generated::NativeTextboxListener>; friend class djinni::JniInterface<::textsort::TextboxListener, ::djinni_generated::NativeTextboxListener>;
friend class djinni::JavaProxyCache<JavaProxy>; friend class djinni::JavaProxyCache<JavaProxy>;
}; };
......
...@@ -183,13 +183,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) { ...@@ -183,13 +183,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
val jniClassName = spec.jniClassIdentStyle(ident) val jniClassName = spec.jniClassIdentStyle(ident)
val fqJniClassName = withNs(Some(spec.jniNamespace), jniClassName) val fqJniClassName = withNs(Some(spec.jniNamespace), jniClassName)
val classLookup = toJavaClassLookup(ident, spec.javaPackage) val classLookup = toJavaClassLookup(ident, spec.javaPackage)
val (baseClassName, baseClassArgs) = (i.ext.java, i.ext.cpp) match { val baseType = s"djinni::JniInterface<$selfQ, $jniClassName>"
case (true, true) => throw new AssertionError("an interface cannot be both +c and +j")
case (false, true) => ("JniInterfaceCppExt", s"<$selfQ>")
case (true, false) => ("JniInterfaceJavaExt", s"<$selfQ, $jniClassName>")
case (false, false) => throw new AssertionError("interface isn't implementable on either side?")
}
val baseType = s"djinni::"+baseClassName+baseClassArgs
def writeJniPrototype(w: IndentWriter) { def writeJniPrototype(w: IndentWriter) {
writeJniTypeParams(w, typeParams) writeJniTypeParams(w, typeParams)
...@@ -198,9 +192,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) { ...@@ -198,9 +192,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
w.wl(s"using CppType = std::shared_ptr<$selfQ>;") w.wl(s"using CppType = std::shared_ptr<$selfQ>;")
w.wl(s"using JniType = jobject;") w.wl(s"using JniType = jobject;")
w.wl w.wl
if (!i.ext.java) {
w.wl(s"static jobject toJava(JNIEnv* jniEnv, std::shared_ptr<$selfQ> c) { return djinni::JniClass<$fqJniClassName>::get()._toJava(jniEnv, c); }") w.wl(s"static jobject toJava(JNIEnv* jniEnv, std::shared_ptr<$selfQ> c) { return djinni::JniClass<$fqJniClassName>::get()._toJava(jniEnv, c); }")
}
w.wl(s"static std::shared_ptr<$selfQ> fromJava(JNIEnv* jniEnv, jobject j) { return djinni::JniClass<$fqJniClassName>::get()._fromJava(jniEnv, j); }") w.wl(s"static std::shared_ptr<$selfQ> fromJava(JNIEnv* jniEnv, jobject j) { return djinni::JniClass<$fqJniClassName>::get()._fromJava(jniEnv, j); }")
w.wl w.wl
if (i.ext.java) { if (i.ext.java) {
...@@ -224,7 +216,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) { ...@@ -224,7 +216,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
w.wl w.wl
w.wlOutdent(s"private:") w.wlOutdent(s"private:")
w.wl(s"using djinni::JavaProxyCacheEntry::getGlobalRef;") w.wl(s"using djinni::JavaProxyCacheEntry::getGlobalRef;")
w.wl(s"friend class djinni::JniInterfaceJavaExt<$selfQ, $fqJniClassName>;") w.wl(s"friend class djinni::JniInterface<$selfQ, $fqJniClassName>;")
w.wl(s"friend class djinni::JavaProxyCache<JavaProxy>;") w.wl(s"friend class djinni::JavaProxyCache<JavaProxy>;")
} }
} }
...@@ -236,7 +228,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) { ...@@ -236,7 +228,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
} }
def writeJniBody(w: IndentWriter) { def writeJniBody(w: IndentWriter) {
val baseClassParam = if (i.ext.cpp) q(classLookup+"$NativeProxy") else "" val baseClassParam = if (i.ext.cpp) q(classLookup+"$CppProxy") else ""
writeJniTypeParams(w, typeParams) writeJniTypeParams(w, typeParams)
w.wl(s"$jniClassName::$jniClassName() : $baseType($baseClassParam) {}") w.wl(s"$jniClassName::$jniClassName() : $baseType($baseClassParam) {}")
w.wl w.wl
...@@ -300,7 +292,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) { ...@@ -300,7 +292,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
} }
} }
else { else {
w.wl(s"CJNIEXPORT $jniRetType JNICALL ${prefix}_00024NativeProxy_$methodNameMunged(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef${preComma(paramList)})").braced { w.wl(s"CJNIEXPORT $jniRetType JNICALL ${prefix}_00024CppProxy_$methodNameMunged(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef${preComma(paramList)})").braced {
val zero = "0 /* value doesn't matter*/" val zero = "0 /* value doesn't matter*/"
w.w("try").bracedEnd(s" JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, ${ret.fold("")(s => zero)})") { w.w("try").bracedEnd(s" JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, ${ret.fold("")(s => zero)})") {
w.wl(s"DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef);") w.wl(s"DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef);")
...@@ -310,13 +302,13 @@ class JNIGenerator(spec: Spec) extends Generator(spec) { ...@@ -310,13 +302,13 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
} }
} }
nativeHook("nativeDestroy", false, Seq.empty, None, { nativeHook("nativeDestroy", false, Seq.empty, None, {
w.wl(s"delete reinterpret_cast<std::shared_ptr<$selfQ>*>(nativeRef);") w.wl(s"delete reinterpret_cast<djinni::CppProxyHandle<$selfQ>*>(nativeRef);")
}) })
for (m <- i.methods) { for (m <- i.methods) {
val nativeAddon = if (m.static) "" else "native_" val nativeAddon = if (m.static) "" else "native_"
nativeHook(nativeAddon + idJava.method(m.ident), m.static, m.params, m.ret, { nativeHook(nativeAddon + idJava.method(m.ident), m.static, m.params, m.ret, {
//w.wl(s"::${spec.jniNamespace}::JniLocalScope jscope(jniEnv, 10);") //w.wl(s"::${spec.jniNamespace}::JniLocalScope jscope(jniEnv, 10);")
if (!m.static) w.wl(s"const std::shared_ptr<$selfQ> & ref = *reinterpret_cast<const std::shared_ptr<$selfQ>*>(nativeRef);") if (!m.static) w.wl(s"const std::shared_ptr<$selfQ> & ref = djinni::CppProxyHandle<$selfQ>::get(nativeRef);")
for (p <- m.params) { for (p <- m.params) {
val jniHelperClass = toJniHelperClass(p.ty) val jniHelperClass = toJniHelperClass(p.ty)
val cppType = toCppType(p.ty, spec.cppNamespace) val cppType = toCppType(p.ty, spec.cppNamespace)
......
...@@ -165,11 +165,11 @@ class JavaGenerator(spec: Spec) extends Generator(spec) { ...@@ -165,11 +165,11 @@ class JavaGenerator(spec: Spec) extends Generator(spec) {
if (i.ext.cpp) { if (i.ext.cpp) {
w.wl w.wl
javaAnnotationHeader.foreach(w.wl) javaAnnotationHeader.foreach(w.wl)
w.wl(s"public static final class NativeProxy$typeParamList extends $javaClass$typeParamList").braced { w.wl(s"public static final class CppProxy$typeParamList extends $javaClass$typeParamList").braced {
w.wl("private final long nativeRef;") w.wl("private final long nativeRef;")
w.wl("private final AtomicBoolean destroyed = new AtomicBoolean(false);") w.wl("private final AtomicBoolean destroyed = new AtomicBoolean(false);")
w.wl w.wl
w.wl(s"private NativeProxy(long nativeRef)").braced { w.wl(s"private CppProxy(long nativeRef)").braced {
w.wl("if (nativeRef == 0) throw new RuntimeException(\"nativeRef is zero\");") w.wl("if (nativeRef == 0) throw new RuntimeException(\"nativeRef is zero\");")
w.wl(s"this.nativeRef = nativeRef;") w.wl(s"this.nativeRef = nativeRef;")
} }
...@@ -183,7 +183,7 @@ class JavaGenerator(spec: Spec) extends Generator(spec) { ...@@ -183,7 +183,7 @@ class JavaGenerator(spec: Spec) extends Generator(spec) {
w.wl("destroy();") w.wl("destroy();")
w.wl("super.finalize();") w.wl("super.finalize();")
} }
for (m <- i.methods if !m.static) { // Static methods not in NativeProxy for (m <- i.methods if !m.static) { // Static methods not in CppProxy
val ret = m.ret.fold("void")(toJavaType(_)) val ret = m.ret.fold("void")(toJavaType(_))
val returnStmt = m.ret.fold("")(_ => "return ") val returnStmt = m.ret.fold("")(_ => "return ")
val params = m.params.map(p => toJavaType(p.ty)+" "+idJava.local(p.ident)).mkString(", ") val params = m.params.map(p => toJavaType(p.ty)+" "+idJava.local(p.ident)).mkString(", ")
......
...@@ -51,19 +51,19 @@ JNIEnv * jniGetThreadEnv() { ...@@ -51,19 +51,19 @@ JNIEnv * jniGetThreadEnv() {
return env; return env;
} }
void GlobalRefDeleter::operator() (jobject globalRef) noexcept { static JNIEnv * getOptThreadEnv() {
if (!globalRef || !g_cachedJVM) { if (!g_cachedJVM) {
return; return nullptr;
} }
// Special case: ignore GlobalRef deletions that happen after this thread has been // Special case: this allows us to ignore GlobalRef deletions that happen after this
// detached. (This can happen during process shutdown, so there's no need to release the // thread has been detached. (This is known to happen during process shutdown, when
// ref anyway.) // there's no need to release the ref anyway.)
JNIEnv * env = nullptr; JNIEnv * env = nullptr;
const jint get_res = g_cachedJVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); const jint get_res = g_cachedJVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
if (get_res == JNI_EDETACHED) { if (get_res == JNI_EDETACHED) {
return; return nullptr;
} }
// Still bail on any other error. // Still bail on any other error.
...@@ -72,11 +72,29 @@ void GlobalRefDeleter::operator() (jobject globalRef) noexcept { ...@@ -72,11 +72,29 @@ void GlobalRefDeleter::operator() (jobject globalRef) noexcept {
std::abort(); std::abort();
} }
return env;
}
void WeakGlobalRefDeleter::operator() (jobject wgr) noexcept {
if (wgr) {
if (JNIEnv * env = getOptThreadEnv()) {
env->DeleteWeakGlobalRef(wgr);
}
}
}
void GlobalRefDeleter::operator() (jobject globalRef) noexcept {
if (globalRef) {
if (JNIEnv * env = getOptThreadEnv()) {
env->DeleteGlobalRef(globalRef); env->DeleteGlobalRef(globalRef);
}
}
} }
void LocalRefDeleter::operator() (jobject localRef) noexcept { void LocalRefDeleter::operator() (jobject localRef) noexcept {
if (localRef) {
jniGetThreadEnv()->DeleteLocalRef(localRef); jniGetThreadEnv()->DeleteLocalRef(localRef);
}
} }
void jniExceptionCheck(JNIEnv * env) { void jniExceptionCheck(JNIEnv * env) {
...@@ -442,4 +460,54 @@ std::shared_ptr<void> javaProxyCacheLookup(jobject obj, std::pair<std::shared_pt ...@@ -442,4 +460,54 @@ std::shared_ptr<void> javaProxyCacheLookup(jobject obj, std::pair<std::shared_pt
return ret.first; return ret.first;
} }
CppProxyClassInfo::CppProxyClassInfo(const char * className)
: clazz(jniFindClass(className)),
constructor(jniGetMethodID(clazz.get(), "<init>", "(J)V")),
idField(jniGetFieldID(clazz.get(), "nativeRef", "J")) {
}
CppProxyClassInfo::CppProxyClassInfo() : constructor{}, idField{} {
}
CppProxyClassInfo::~CppProxyClassInfo() {
}
struct CppProxyCacheState {
std::mutex mtx;
std::unordered_map<void *, WeakGlobalRef<jobject>> m;
static CppProxyCacheState & get() {
static CppProxyCacheState st;
return st;
}
};
/*static*/ void JniCppProxyCache::erase(void * key) {
CppProxyCacheState & st = CppProxyCacheState::get();
const std::lock_guard<std::mutex> lock(st.mtx);
st.m.erase(key);
}
/*static*/ jobject JniCppProxyCache::get(const std::shared_ptr<void> & cppObj,
JNIEnv * jniEnv,
const CppProxyClassInfo & proxyClass,
jobject (*factory)(const std::shared_ptr<void> &,
JNIEnv *,
const CppProxyClassInfo &)) {
CppProxyCacheState & st = CppProxyCacheState::get();
const std::lock_guard<std::mutex> lock(st.mtx);
auto it = st.m.find(cppObj.get());
if (it != st.m.end()) {
jobject localRef = jniEnv->NewLocalRef(it->second.get());
if (localRef) {
return localRef;
}
}
jobject wrapper = factory(cppObj, jniEnv, proxyClass);
st.m.emplace(cppObj.get(), WeakGlobalRef<jobject>(jniEnv, wrapper));
return wrapper;
}
} // namespace djinni } // namespace djinni
This diff is collapsed.
...@@ -6,5 +6,6 @@ ...@@ -6,5 +6,6 @@
@import "exception.djinni" @import "exception.djinni"
@import "client_interface.djinni" @import "client_interface.djinni"
@import "enum.djinni" @import "enum.djinni"
@import "token.djinni"
@import "test.djinni" @import "test.djinni"
@import "inttypes.djinni" @import "inttypes.djinni"
...@@ -20,6 +20,11 @@ test_helpers = interface +c { ...@@ -20,6 +20,11 @@ test_helpers = interface +c {
static check_enum_map(m: map<color, string>); static check_enum_map(m: map<color, string>);
static token_id(t: token): token;
static create_cpp_token(): token;
static check_cpp_token(t: token);
static cpp_token_id(t: token): i64;
static return_none(): optional<i32>; static return_none(): optional<i32>;
# Ensures that we generate integer translation code # Ensures that we generate integer translation code
......
token = interface +c +j {
}
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <unordered_map> #include <unordered_map>
class ClientInterface; class ClientInterface;
class Token;
class TestHelpers { class TestHelpers {
public: public:
...@@ -51,6 +52,14 @@ public: ...@@ -51,6 +52,14 @@ public:
static void check_enum_map(const std::unordered_map<color, std::string> & m); static void check_enum_map(const std::unordered_map<color, std::string> & m);
static std::shared_ptr<Token> token_id(const std::shared_ptr<Token> & t);
static std::shared_ptr<Token> create_cpp_token();
static void check_cpp_token(const std::shared_ptr<Token> & t);
static int64_t cpp_token_id(const std::shared_ptr<Token> & t);
static std::experimental::optional<int32_t> return_none(); static std::experimental::optional<int32_t> return_none();
/** Ensures that we generate integer translation code */ /** Ensures that we generate integer translation code */
......
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from token.djinni
#pragma once
class Token {
public:
virtual ~Token() {}
};
...@@ -10,12 +10,12 @@ public abstract class CppException { ...@@ -10,12 +10,12 @@ public abstract class CppException {
public static native CppException get(); public static native CppException get();
public static final class NativeProxy extends CppException public static final class CppProxy extends CppException
{ {
private final long nativeRef; private final long nativeRef;
private final AtomicBoolean destroyed = new AtomicBoolean(false); private final AtomicBoolean destroyed = new AtomicBoolean(false);
private NativeProxy(long nativeRef) private CppProxy(long nativeRef)
{ {
if (nativeRef == 0) throw new RuntimeException("nativeRef is zero"); if (nativeRef == 0) throw new RuntimeException("nativeRef is zero");
this.nativeRef = nativeRef; this.nativeRef = nativeRef;
......
...@@ -37,17 +37,25 @@ public abstract class TestHelpers { ...@@ -37,17 +37,25 @@ public abstract class TestHelpers {
public static native void checkEnumMap(HashMap<Color, String> m); public static native void checkEnumMap(HashMap<Color, String> m);
public static native Token tokenId(Token t);
public static native Token createCppToken();
public static native void checkCppToken(Token t);
public static native long cppTokenId(Token t);
public static native Integer returnNone(); public static native Integer returnNone();
/** Ensures that we generate integer translation code */ /** Ensures that we generate integer translation code */
public static native AssortedIntegers assortedIntegersId(AssortedIntegers i); public static native AssortedIntegers assortedIntegersId(AssortedIntegers i);
public static final class NativeProxy extends TestHelpers public static final class CppProxy extends TestHelpers
{ {
private final long nativeRef; private final long nativeRef;
private final AtomicBoolean destroyed = new AtomicBoolean(false); private final AtomicBoolean destroyed = new AtomicBoolean(false);
private NativeProxy(long nativeRef) private CppProxy(long nativeRef)
{ {
if (nativeRef == 0) throw new RuntimeException("nativeRef is zero"); if (nativeRef == 0) throw new RuntimeException("nativeRef is zero");
this.nativeRef = nativeRef; this.nativeRef = nativeRef;
......
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from token.djinni
package com.dropbox.djinni.test;
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class Token {
public static final class CppProxy extends Token
{
private final long nativeRef;
private final AtomicBoolean destroyed = new AtomicBoolean(false);
private CppProxy(long nativeRef)
{
if (nativeRef == 0) throw new RuntimeException("nativeRef is zero");
this.nativeRef = nativeRef;
}
private native void nativeDestroy(long nativeRef);
public void destroy()
{
boolean destroyed = this.destroyed.getAndSet(true);
if (!destroyed) nativeDestroy(this.nativeRef);
}
protected void finalize() throws java.lang.Throwable
{
destroy();
super.finalize();
}
}
}
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
namespace djinni_generated { namespace djinni_generated {
NativeClientInterface::NativeClientInterface() : djinni::JniInterfaceJavaExt<ClientInterface, NativeClientInterface>() {} NativeClientInterface::NativeClientInterface() : djinni::JniInterface<ClientInterface, NativeClientInterface>() {}
NativeClientInterface::JavaProxy::JavaProxy(jobject obj) : JavaProxyCacheEntry(obj) {} NativeClientInterface::JavaProxy::JavaProxy(jobject obj) : JavaProxyCacheEntry(obj) {}
......
...@@ -8,11 +8,12 @@ ...@@ -8,11 +8,12 @@
namespace djinni_generated { namespace djinni_generated {
class NativeClientInterface final : djinni::JniInterfaceJavaExt<ClientInterface, NativeClientInterface> { class NativeClientInterface final : djinni::JniInterface<ClientInterface, NativeClientInterface> {
public: public:
using CppType = std::shared_ptr<ClientInterface>; using CppType = std::shared_ptr<ClientInterface>;
using JniType = jobject; 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); } static std::shared_ptr<ClientInterface> fromJava(JNIEnv* jniEnv, jobject j) { return djinni::JniClass<::djinni_generated::NativeClientInterface>::get()._fromJava(jniEnv, j); }
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/ClientInterface") }; const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/ClientInterface") };
...@@ -25,7 +26,7 @@ public: ...@@ -25,7 +26,7 @@ public:
private: private:
using djinni::JavaProxyCacheEntry::getGlobalRef; using djinni::JavaProxyCacheEntry::getGlobalRef;
friend class djinni::JniInterfaceJavaExt<ClientInterface, ::djinni_generated::NativeClientInterface>; friend class djinni::JniInterface<ClientInterface, ::djinni_generated::NativeClientInterface>;
friend class djinni::JavaProxyCache<JavaProxy>; friend class djinni::JavaProxyCache<JavaProxy>;
}; };
......
...@@ -7,23 +7,23 @@ ...@@ -7,23 +7,23 @@
namespace djinni_generated { namespace djinni_generated {
NativeCppException::NativeCppException() : djinni::JniInterfaceCppExt<CppException>("com/dropbox/djinni/test/CppException$NativeProxy") {} NativeCppException::NativeCppException() : djinni::JniInterface<CppException, NativeCppException>("com/dropbox/djinni/test/CppException$CppProxy") {}
using namespace ::djinni_generated; using namespace ::djinni_generated;
CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_CppException_00024NativeProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef) CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_CppException_00024CppProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef)
{ {
try { try {
DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef); DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef);
delete reinterpret_cast<std::shared_ptr<CppException>*>(nativeRef); delete reinterpret_cast<djinni::CppProxyHandle<CppException>*>(nativeRef);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, ) } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
} }
CJNIEXPORT jint JNICALL Java_com_dropbox_djinni_test_CppException_00024NativeProxy_native_1throwAnException(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef) CJNIEXPORT jint JNICALL Java_com_dropbox_djinni_test_CppException_00024CppProxy_native_1throwAnException(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef)
{ {
try { try {
DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef); DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef);
const std::shared_ptr<CppException> & ref = *reinterpret_cast<const std::shared_ptr<CppException>*>(nativeRef); const std::shared_ptr<CppException> & ref = djinni::CppProxyHandle<CppException>::get(nativeRef);
int32_t cr = ref->throw_an_exception(); int32_t cr = ref->throw_an_exception();
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
namespace djinni_generated { namespace djinni_generated {
class NativeCppException final : djinni::JniInterfaceCppExt<CppException> { class NativeCppException final : djinni::JniInterface<CppException, NativeCppException> {
public: public:
using CppType = std::shared_ptr<CppException>; using CppType = std::shared_ptr<CppException>;
using JniType = jobject; using JniType = jobject;
......
...@@ -15,18 +15,19 @@ ...@@ -15,18 +15,19 @@
#include "NativeNestedCollection.hpp" #include "NativeNestedCollection.hpp"
#include "NativePrimitiveList.hpp" #include "NativePrimitiveList.hpp"
#include "NativeSetRecord.hpp" #include "NativeSetRecord.hpp"
#include "NativeToken.hpp"
namespace djinni_generated { namespace djinni_generated {
NativeTestHelpers::NativeTestHelpers() : djinni::JniInterfaceCppExt<TestHelpers>("com/dropbox/djinni/test/TestHelpers$NativeProxy") {} NativeTestHelpers::NativeTestHelpers() : djinni::JniInterface<TestHelpers, NativeTestHelpers>("com/dropbox/djinni/test/TestHelpers$CppProxy") {}
using namespace ::djinni_generated; using namespace ::djinni_generated;
CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_00024NativeProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef) CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_00024CppProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef)
{ {
try { try {
DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef); DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef);
delete reinterpret_cast<std::shared_ptr<TestHelpers>*>(nativeRef); delete reinterpret_cast<djinni::CppProxyHandle<TestHelpers>*>(nativeRef);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, ) } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
} }
...@@ -198,6 +199,51 @@ CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkEnumMap(JN ...@@ -198,6 +199,51 @@ CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkEnumMap(JN
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, ) } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
} }
CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_tokenId(JNIEnv* jniEnv, jobject /*this*/, jobject j_t)
{
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);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */ )
}
CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_createCppToken(JNIEnv* jniEnv, jobject /*this*/)
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::shared_ptr<Token> cr = TestHelpers::create_cpp_token();
return NativeToken::toJava(jniEnv, cr);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */ )
}
CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkCppToken(JNIEnv* jniEnv, jobject /*this*/, jobject j_t)
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
std::shared_ptr<Token> c_t = NativeToken::fromJava(jniEnv, j_t);
TestHelpers::check_cpp_token(c_t);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
}
CJNIEXPORT jlong JNICALL Java_com_dropbox_djinni_test_TestHelpers_cppTokenId(JNIEnv* jniEnv, jobject /*this*/, jobject j_t)
{
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);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */ )
}
CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_returnNone(JNIEnv* jniEnv, jobject /*this*/) CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_returnNone(JNIEnv* jniEnv, jobject /*this*/)
{ {
try { try {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
namespace djinni_generated { namespace djinni_generated {
class NativeTestHelpers final : djinni::JniInterfaceCppExt<TestHelpers> { class NativeTestHelpers final : djinni::JniInterface<TestHelpers, NativeTestHelpers> {
public: public:
using CppType = std::shared_ptr<TestHelpers>; using CppType = std::shared_ptr<TestHelpers>;
using JniType = jobject; using JniType = jobject;
......
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from token.djinni
#include "NativeToken.hpp" // my header
namespace djinni_generated {
NativeToken::NativeToken() : djinni::JniInterface<Token, NativeToken>("com/dropbox/djinni/test/Token$CppProxy") {}
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)
{
try {
DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef);
delete reinterpret_cast<djinni::CppProxyHandle<Token>*>(nativeRef);
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
}
} // namespace djinni_generated
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from token.djinni
#pragma once
#include "djinni_support.hpp"
#include "token.hpp"
namespace djinni_generated {
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); }
const djinni::GlobalRef<jclass> clazz { djinni::jniFindClass("com/dropbox/djinni/test/Token") };
class JavaProxy final : djinni::JavaProxyCacheEntry, public Token {
public:
JavaProxy(jobject obj);
private:
using djinni::JavaProxyCacheEntry::getGlobalRef;
friend class djinni::JniInterface<Token, ::djinni_generated::NativeToken>;
friend class djinni::JavaProxyCache<JavaProxy>;
};
private:
NativeToken();
friend class djinni::JniClass<::djinni_generated::NativeToken>;
};
} // namespace djinni_generated
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#import "DBClientInterface.h" #import "DBClientInterface.h"
#import "DBColor.h" #import "DBColor.h"
#import "DBToken.h"
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@class DBAssortedIntegers; @class DBAssortedIntegers;
@class DBMapListRecord; @class DBMapListRecord;
...@@ -43,6 +44,14 @@ ...@@ -43,6 +44,14 @@
+ (void)checkEnumMap:(NSMutableDictionary *)m; + (void)checkEnumMap:(NSMutableDictionary *)m;
+ (id <DBToken>)tokenId:(id <DBToken>)t;
+ (id <DBToken>)createCppToken;
+ (void)checkCppToken:(id <DBToken>)t;
+ (int64_t)cppTokenId:(id <DBToken>)t;
+ (NSNumber *)returnNone; + (NSNumber *)returnNone;
/** Ensures that we generate integer translation code */ /** Ensures that we generate integer translation code */
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#import "DBPrimitiveList+Private.h" #import "DBPrimitiveList+Private.h"
#import "DBSetRecord+Private.h" #import "DBSetRecord+Private.h"
#import "DBTestHelpers.h" #import "DBTestHelpers.h"
#import "DBTokenCppProxy+Private.h"
#import "DJIError.h" #import "DJIError.h"
#include <exception> #include <exception>
#include <utility> #include <utility>
...@@ -191,6 +192,39 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th ...@@ -191,6 +192,39 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th
} DJINNI_TRANSLATE_EXCEPTIONS() } DJINNI_TRANSLATE_EXCEPTIONS()
} }
+ (id <DBToken>)tokenId:(id <DBToken>)t {
try {
std::shared_ptr<Token> cppT = [(DBTokenCppProxy *)t cppRef];
std::shared_ptr<Token> cppRet = TestHelpers::token_id(std::move(cppT));
id <DBToken> objcRet = [DBTokenCppProxy tokenWithCpp:cppRet];
return objcRet;
} DJINNI_TRANSLATE_EXCEPTIONS()
}
+ (id <DBToken>)createCppToken {
try {
std::shared_ptr<Token> cppRet = TestHelpers::create_cpp_token();
id <DBToken> objcRet = [DBTokenCppProxy tokenWithCpp:cppRet];
return objcRet;
} DJINNI_TRANSLATE_EXCEPTIONS()
}
+ (void)checkCppToken:(id <DBToken>)t {
try {
std::shared_ptr<Token> cppT = [(DBTokenCppProxy *)t cppRef];
TestHelpers::check_cpp_token(std::move(cppT));
} DJINNI_TRANSLATE_EXCEPTIONS()
}
+ (int64_t)cppTokenId:(id <DBToken>)t {
try {
std::shared_ptr<Token> cppT = [(DBTokenCppProxy *)t cppRef];
int64_t cppRet = TestHelpers::cpp_token_id(std::move(cppT));
int64_t objcRet = cppRet;
return objcRet;
} DJINNI_TRANSLATE_EXCEPTIONS()
}
+ (NSNumber *)returnNone { + (NSNumber *)returnNone {
try { try {
std::experimental::optional<int32_t> cppRet = TestHelpers::return_none(); std::experimental::optional<int32_t> cppRet = TestHelpers::return_none();
......
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from token.djinni
@protocol DBToken
@end
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from token.djinni
#import "DBToken.h"
#import "DBTokenCppProxy.h"
#include "token.hpp"
#import "DJICppWrapperCache+Private.h"
#import <Foundation/Foundation.h>
#include <memory>
@interface DBTokenCppProxy ()
@property (nonatomic, readonly) std::shared_ptr<Token> cppRef;
+ (id)tokenWithCpp:(const std::shared_ptr<Token> &)cppRef;
- (id)initWithCpp:(const std::shared_ptr<Token> &)cppRef;
@end
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from token.djinni
#import "DBToken.h"
#import <Foundation/Foundation.h>
@interface DBTokenCppProxy : NSObject <DBToken>
@end
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from token.djinni
#import "DBTokenCppProxy+Private.h"
#import "DBToken.h"
#import "DJIError.h"
#include <exception>
#include <utility>
static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file");
@implementation DBTokenCppProxy
- (id)initWithCpp:(const std::shared_ptr<Token> &)cppRef
{
if (self = [super init]) {
_cppRef = cppRef;
}
return self;
}
- (void)dealloc
{
djinni::DbxCppWrapperCache<Token> & cache = djinni::DbxCppWrapperCache<Token>::getInstance();
cache.remove(_cppRef);
}
+ (id)tokenWithCpp:(const std::shared_ptr<Token> &)cppRef
{
djinni::DbxCppWrapperCache<Token> & cache = djinni::DbxCppWrapperCache<Token>::getInstance();
return cache.get(cppRef, [] (const std::shared_ptr<Token> & p) { return [[DBTokenCppProxy alloc] initWithCpp:p]; });
}
@end
#include "test_helpers.hpp" #include "test_helpers.hpp"
#include "client_returned_record.hpp" #include "client_returned_record.hpp"
#include "client_interface.hpp" #include "client_interface.hpp"
#include "token.hpp"
#include <exception> #include <exception>
SetRecord TestHelpers::get_set_record() { SetRecord TestHelpers::get_set_record() {
...@@ -85,6 +86,25 @@ void TestHelpers::check_client_interface_nonascii(const std::shared_ptr<ClientIn ...@@ -85,6 +86,25 @@ void TestHelpers::check_client_interface_nonascii(const std::shared_ptr<ClientIn
} }
} }
std::shared_ptr<Token> TestHelpers::token_id(const std::shared_ptr<Token> & in) {
return in;
}
class CppToken : public Token {};
std::shared_ptr<Token> TestHelpers::create_cpp_token() {
return std::make_shared<CppToken>();
}
void TestHelpers::check_cpp_token(const std::shared_ptr<Token> & in) {
// Throws bad_cast if type is wrong
(void)dynamic_cast<CppToken &>(*in);
}
int64_t TestHelpers::cpp_token_id(const std::shared_ptr<Token> & in) {
return reinterpret_cast<int64_t>(in.get());
}
std::experimental::optional<int32_t> TestHelpers::return_none() { std::experimental::optional<int32_t> TestHelpers::return_none() {
return {}; return {};
} }
......
...@@ -16,6 +16,7 @@ public class AllTests extends TestSuite { ...@@ -16,6 +16,7 @@ public class AllTests extends TestSuite {
mySuite.addTestSuite(ClientInterfaceTest.class); mySuite.addTestSuite(ClientInterfaceTest.class);
mySuite.addTestSuite(EnumTest.class); mySuite.addTestSuite(EnumTest.class);
mySuite.addTestSuite(IntegerTest.class); mySuite.addTestSuite(IntegerTest.class);
mySuite.addTestSuite(TokenTest.class);
return mySuite; return mySuite;
} }
......
package com.dropbox.djinni.test;
import junit.framework.TestCase;
public class TokenTest extends TestCase {
private class JavaToken extends Token {
}
@Override
protected void setUp() {
}
public void testTokens() {
Token jt = new JavaToken();
assertSame(TestHelpers.tokenId(jt), jt);
}
public void testNullToken() {
assertSame(TestHelpers.tokenId(null), null);
}
public void testCppToken() {
Token ct = TestHelpers.createCppToken();
assertSame(TestHelpers.tokenId(ct), ct);
TestHelpers.checkCppToken(ct);
ct = null;
System.gc();
System.runFinalization();
}
public void testNotCppToken() {
boolean threw = false;
try {
TestHelpers.checkCppToken(new JavaToken());
} catch (RuntimeException e) {
threw = true;
}
assertTrue(threw);
System.gc();
}
}
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
A2059B6219DF7DDE006A2896 /* DBColorTranslator.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2059B6019DF7DDE006A2896 /* DBColorTranslator.mm */; }; A2059B6219DF7DDE006A2896 /* DBColorTranslator.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2059B6019DF7DDE006A2896 /* DBColorTranslator.mm */; };
A227B6A91A0D79F10003BBAC /* assorted_integers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A227B6A71A0D79F10003BBAC /* assorted_integers.cpp */; }; A227B6A91A0D79F10003BBAC /* assorted_integers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A227B6A71A0D79F10003BBAC /* assorted_integers.cpp */; };
A227B6AD1A0D7A290003BBAC /* DBAssortedIntegers.mm in Sources */ = {isa = PBXBuildFile; fileRef = A227B6AB1A0D7A290003BBAC /* DBAssortedIntegers.mm */; }; A227B6AD1A0D7A290003BBAC /* DBAssortedIntegers.mm in Sources */ = {isa = PBXBuildFile; fileRef = A227B6AB1A0D7A290003BBAC /* DBAssortedIntegers.mm */; };
A21557A91A16DC5000084E93 /* DBTokenCppProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = A21557A71A16DC5000084E93 /* DBTokenCppProxy.mm */; };
A278D45019BA33CB006FD937 /* DBTestHelpersCppProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = A278D44E19BA33CB006FD937 /* DBTestHelpersCppProxy.mm */; }; A278D45019BA33CB006FD937 /* DBTestHelpersCppProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = A278D44E19BA33CB006FD937 /* DBTestHelpersCppProxy.mm */; };
A278D45319BA3601006FD937 /* test_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A278D45219BA3601006FD937 /* test_helpers.cpp */; }; A278D45319BA3601006FD937 /* test_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A278D45219BA3601006FD937 /* test_helpers.cpp */; };
A2CB54B419BA6E6000A9E600 /* DJIError.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2CB54B319BA6E6000A9E600 /* DJIError.mm */; }; A2CB54B419BA6E6000A9E600 /* DJIError.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2CB54B319BA6E6000A9E600 /* DJIError.mm */; };
...@@ -142,12 +143,17 @@ ...@@ -142,12 +143,17 @@
A227B6AA1A0D7A290003BBAC /* DBAssortedIntegers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DBAssortedIntegers.h; sourceTree = "<group>"; }; A227B6AA1A0D7A290003BBAC /* DBAssortedIntegers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DBAssortedIntegers.h; sourceTree = "<group>"; };
A227B6AB1A0D7A290003BBAC /* DBAssortedIntegers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DBAssortedIntegers.mm; sourceTree = "<group>"; }; A227B6AB1A0D7A290003BBAC /* DBAssortedIntegers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DBAssortedIntegers.mm; sourceTree = "<group>"; };
A227B6AC1A0D7A290003BBAC /* DBAssortedIntegers+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "DBAssortedIntegers+Private.h"; sourceTree = "<group>"; }; A227B6AC1A0D7A290003BBAC /* DBAssortedIntegers+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "DBAssortedIntegers+Private.h"; sourceTree = "<group>"; };
A21557A51A16DC5000084E93 /* DBToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DBToken.h; sourceTree = "<group>"; };
A21557A61A16DC5000084E93 /* DBTokenCppProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DBTokenCppProxy.h; sourceTree = "<group>"; };
A21557A71A16DC5000084E93 /* DBTokenCppProxy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DBTokenCppProxy.mm; sourceTree = "<group>"; };
A21557A81A16DC5000084E93 /* DBTokenCppProxy+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "DBTokenCppProxy+Private.h"; sourceTree = "<group>"; };
A278D44C19BA33CB006FD937 /* DBTestHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DBTestHelpers.h; sourceTree = "<group>"; }; A278D44C19BA33CB006FD937 /* DBTestHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DBTestHelpers.h; sourceTree = "<group>"; };
A278D44D19BA33CB006FD937 /* DBTestHelpersCppProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DBTestHelpersCppProxy.h; sourceTree = "<group>"; }; A278D44D19BA33CB006FD937 /* DBTestHelpersCppProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DBTestHelpersCppProxy.h; sourceTree = "<group>"; };
A278D44E19BA33CB006FD937 /* DBTestHelpersCppProxy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DBTestHelpersCppProxy.mm; sourceTree = "<group>"; }; A278D44E19BA33CB006FD937 /* DBTestHelpersCppProxy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DBTestHelpersCppProxy.mm; sourceTree = "<group>"; };
A278D44F19BA33CB006FD937 /* DBTestHelpersCppProxy+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "DBTestHelpersCppProxy+Private.h"; sourceTree = "<group>"; }; A278D44F19BA33CB006FD937 /* DBTestHelpersCppProxy+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "DBTestHelpersCppProxy+Private.h"; sourceTree = "<group>"; };
A278D45119BA3428006FD937 /* test_helpers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = test_helpers.hpp; sourceTree = "<group>"; }; A278D45119BA3428006FD937 /* test_helpers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = test_helpers.hpp; sourceTree = "<group>"; };
A278D45219BA3601006FD937 /* test_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_helpers.cpp; sourceTree = "<group>"; }; A278D45219BA3601006FD937 /* test_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_helpers.cpp; sourceTree = "<group>"; };
A2CAD0871A16CA1800080DF0 /* token.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = token.hpp; sourceTree = "<group>"; };
A2CB54B319BA6E6000A9E600 /* DJIError.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DJIError.mm; sourceTree = "<group>"; }; A2CB54B319BA6E6000A9E600 /* DJIError.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DJIError.mm; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
...@@ -265,6 +271,7 @@ ...@@ -265,6 +271,7 @@
children = ( children = (
A227B6A71A0D79F10003BBAC /* assorted_integers.cpp */, A227B6A71A0D79F10003BBAC /* assorted_integers.cpp */,
A227B6A81A0D79F10003BBAC /* assorted_integers.hpp */, A227B6A81A0D79F10003BBAC /* assorted_integers.hpp */,
A2CAD0871A16CA1800080DF0 /* token.hpp */,
A2059B5E19DF7DBA006A2896 /* color.hpp */, A2059B5E19DF7DBA006A2896 /* color.hpp */,
A278D45119BA3428006FD937 /* test_helpers.hpp */, A278D45119BA3428006FD937 /* test_helpers.hpp */,
65BAE6D719A6C7100035F775 /* client_interface.hpp */, 65BAE6D719A6C7100035F775 /* client_interface.hpp */,
...@@ -290,6 +297,10 @@ ...@@ -290,6 +297,10 @@
A227B6AA1A0D7A290003BBAC /* DBAssortedIntegers.h */, A227B6AA1A0D7A290003BBAC /* DBAssortedIntegers.h */,
A227B6AB1A0D7A290003BBAC /* DBAssortedIntegers.mm */, A227B6AB1A0D7A290003BBAC /* DBAssortedIntegers.mm */,
A227B6AC1A0D7A290003BBAC /* DBAssortedIntegers+Private.h */, A227B6AC1A0D7A290003BBAC /* DBAssortedIntegers+Private.h */,
A21557A51A16DC5000084E93 /* DBToken.h */,
A21557A61A16DC5000084E93 /* DBTokenCppProxy.h */,
A21557A71A16DC5000084E93 /* DBTokenCppProxy.mm */,
A21557A81A16DC5000084E93 /* DBTokenCppProxy+Private.h */,
A2059B5F19DF7DDE006A2896 /* DBColor.h */, A2059B5F19DF7DDE006A2896 /* DBColor.h */,
A2059B6019DF7DDE006A2896 /* DBColorTranslator.mm */, A2059B6019DF7DDE006A2896 /* DBColorTranslator.mm */,
A2059B6119DF7DDE006A2896 /* DBColorTranslator+Private.h */, A2059B6119DF7DDE006A2896 /* DBColorTranslator+Private.h */,
...@@ -416,6 +427,7 @@ ...@@ -416,6 +427,7 @@
files = ( files = (
65BAE70B19A6C7100035F775 /* DBPrimitiveList.mm in Sources */, 65BAE70B19A6C7100035F775 /* DBPrimitiveList.mm in Sources */,
6536CD6F19A6C82200DD7715 /* DJIWeakPtrWrapper.mm in Sources */, 6536CD6F19A6C82200DD7715 /* DJIWeakPtrWrapper.mm in Sources */,
A21557A91A16DC5000084E93 /* DBTokenCppProxy.mm in Sources */,
65BAE70819A6C7100035F775 /* DBMapListRecord.mm in Sources */, 65BAE70819A6C7100035F775 /* DBMapListRecord.mm in Sources */,
65BAE70919A6C7100035F775 /* DBMapRecord.mm in Sources */, 65BAE70919A6C7100035F775 /* DBMapRecord.mm in Sources */,
A278D45319BA3601006FD937 /* test_helpers.cpp in Sources */, A278D45319BA3601006FD937 /* test_helpers.cpp in Sources */,
......
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