Commit a48d60eb authored by Jacob Potter's avatar Jacob Potter

Merge branch 'bidirectional-interfaces'

parents d116572f b22615ae
...@@ -22,23 +22,6 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th ...@@ -22,23 +22,6 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th
@end @end
namespace djinni_generated {
auto SortItems::toCpp(ObjcType objc) -> CppType
{
return objc ? objc.cppRef.get() : nullptr;
}
auto SortItems::fromCpp(const CppType& cpp) -> ObjcType
{
return !cpp ? nil : ::djinni::DbxCppWrapperCache<::textsort::SortItems>::getInstance()->get(cpp, [] (const CppType& p)
{
return [[TXSSortItems alloc] initWithCpp:p];
});
}
} // namespace djinni_generated
@implementation TXSSortItems @implementation TXSSortItems
- (id)initWithCpp:(const std::shared_ptr<::textsort::SortItems>&)cppRef - (id)initWithCpp:(const std::shared_ptr<::textsort::SortItems>&)cppRef
...@@ -65,3 +48,25 @@ auto SortItems::fromCpp(const CppType& cpp) -> ObjcType ...@@ -65,3 +48,25 @@ auto SortItems::fromCpp(const CppType& cpp) -> ObjcType
} }
@end @end
namespace djinni_generated {
auto SortItems::toCpp(ObjcType objc) -> CppType
{
if (!objc) {
return nullptr;
}
return objc.cppRef.get();
}
auto SortItems::fromCpp(const CppType& cpp) -> ObjcType
{
if (!cpp) {
return nil;
}
return ::djinni::DbxCppWrapperCache<::textsort::SortItems>::getInstance()->get(cpp, [] (const CppType& p) {
return [[TXSSortItems alloc] initWithCpp:p];
});
}
} // namespace djinni_generated
...@@ -24,15 +24,24 @@ public: ...@@ -24,15 +24,24 @@ public:
} }
}; };
} // namespace djinni_generated
namespace djinni_generated {
auto TextboxListener::toCpp(ObjcType objc) -> CppType auto TextboxListener::toCpp(ObjcType objc) -> CppType
{ {
return objc ? ::djinni::DbxObjcWrapperCache<ObjcProxy>::getInstance()->get(objc) : nullptr; if (!objc) {
return nullptr;
}
return ::djinni::DbxObjcWrapperCache<ObjcProxy>::getInstance()->get(objc);
} }
auto TextboxListener::fromCpp(const CppType& cpp) -> ObjcType auto TextboxListener::fromCpp(const CppType& cpp) -> ObjcType
{ {
assert(!cpp || dynamic_cast<ObjcProxy*>(cpp.get())); if (!cpp) {
return cpp ? static_cast<ObjcProxy&>(*cpp).Handle::get() : nil; return nil;
}
return dynamic_cast<ObjcProxy&>(*cpp).Handle::get();
} }
} // namespace djinni_generated } // namespace djinni_generated
...@@ -147,7 +147,7 @@ class ObjcGenerator(spec: Spec) extends Generator(spec) { ...@@ -147,7 +147,7 @@ class ObjcGenerator(spec: Spec) extends Generator(spec) {
w.wl(s";") w.wl(s";")
} }
w.wl w.wl
if (i.ext.cpp) w.wl(s"@interface $self : NSObject") else w.wl(s"@protocol $self") if (i.ext.objc) w.wl(s"@protocol $self") else w.wl(s"@interface $self : NSObject")
for (m <- i.methods) { for (m <- i.methods) {
w.wl w.wl
writeDoc(w, m.doc) writeDoc(w, m.doc)
......
...@@ -50,12 +50,12 @@ class ObjcMarshal(spec: Spec) extends Marshal(spec) { ...@@ -50,12 +50,12 @@ class ObjcMarshal(spec: Spec) extends Marshal(spec) {
List(ImportRef(q(spec.objcIncludePrefix + headerName(d.name)))) List(ImportRef(q(spec.objcIncludePrefix + headerName(d.name))))
case DInterface => case DInterface =>
val ext = d.body.asInstanceOf[Interface].ext val ext = d.body.asInstanceOf[Interface].ext
if (ext.cpp) { if (ext.objc) {
List(ImportRef("<Foundation/Foundation.h>"), DeclRef(s"@class ${typename(d.name, d.body)};", None))
}
else if (ext.objc) {
List(ImportRef("<Foundation/Foundation.h>"), DeclRef(s"@protocol ${typename(d.name, d.body)};", None)) List(ImportRef("<Foundation/Foundation.h>"), DeclRef(s"@protocol ${typename(d.name, d.body)};", None))
} }
else if (ext.cpp) {
List(ImportRef("<Foundation/Foundation.h>"), DeclRef(s"@class ${typename(d.name, d.body)};", None))
}
else { else {
List() List()
} }
......
...@@ -111,11 +111,24 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) { ...@@ -111,11 +111,24 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) {
refs.body.add("#include <utility>") refs.body.add("#include <utility>")
refs.body.add("#import " + q(spec.objcBaseLibIncludePrefix + "DJIError.h")) refs.body.add("#import " + q(spec.objcBaseLibIncludePrefix + "DJIError.h"))
refs.body.add("#include <exception>") refs.body.add("#include <exception>")
}
if (i.ext.objc) {
refs.body.add("#import " + q(spec.objcBaseLibIncludePrefix + "DJIObjcWrapperCache+Private.h"))
refs.body.add("!#import " + q(spec.objcppIncludePrefix + objcppMarshal.privateHeaderName(ident.name)))
}
writeObjcFile(privateBodyName(ident.name), origin, refs.body, w => { writeObjcFile(privateBodyName(ident.name), origin, refs.body, w => {
arcAssert(w) arcAssert(w)
val objcSelf = if (i.ext.objc && i.ext.cpp) self + "CppProxy" else self
if (i.ext.cpp) {
w.wl w.wl
w.wl(s"@interface $self ()") if (i.ext.objc)
w.wl(s"@interface $objcSelf : NSObject<$self>")
else
w.wl(s"@interface $objcSelf ()")
w.wl w.wl
w.wl(s"@property (nonatomic, readonly) ::djinni::DbxCppWrapperCache<$cppSelf>::Handle cppRef;") w.wl(s"@property (nonatomic, readonly) ::djinni::DbxCppWrapperCache<$cppSelf>::Handle cppRef;")
w.wl w.wl
...@@ -123,21 +136,7 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) { ...@@ -123,21 +136,7 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) {
w.wl w.wl
w.wl("@end") w.wl("@end")
w.wl w.wl
wrapNamespace(w, spec.objcppNamespace, w => { w.wl(s"@implementation $objcSelf")
w.wl(s"auto $helperClass::toCpp(ObjcType objc) -> CppType")
w.braced {
w.wl(s"return objc ? objc.cppRef.get() : nullptr;")
}
w.wl
w.wl(s"auto $helperClass::fromCpp(const CppType& cpp) -> ObjcType")
w.braced {
w.wl(s"return !cpp ? nil : ::djinni::DbxCppWrapperCache<$cppSelf>::getInstance()->get(cpp, [] (const CppType& p)").bracedEnd(");") {
w.wl(s"return [[$self alloc] initWithCpp:p];")
}
}
})
w.wl
w.wl(s"@implementation $self")
w.wl w.wl
w.wl(s"- (id)initWithCpp:(const std::shared_ptr<$cppSelf>&)cppRef") w.wl(s"- (id)initWithCpp:(const std::shared_ptr<$cppSelf>&)cppRef")
w.braced { w.braced {
...@@ -161,16 +160,11 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) { ...@@ -161,16 +160,11 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) {
} }
w.wl w.wl
w.wl("@end") w.wl("@end")
})
} }
if (i.ext.objc) { if (i.ext.objc) {
refs.body.add("#import " + q(spec.objcBaseLibIncludePrefix + "DJIObjcWrapperCache+Private.h"))
refs.body.add("!#import " + q(spec.objcppIncludePrefix + objcppMarshal.privateHeaderName(ident.name)))
writeObjcFile(privateBodyName(ident.name), origin, refs.body, w => {
arcAssert(w)
w.wl w.wl
val objcExtSelf = objcppMarshal.helperClass("objc_proxy")
wrapNamespace(w, spec.objcppNamespace, w => { wrapNamespace(w, spec.objcppNamespace, w => {
w.wl(s"class $helperClass::ObjcProxy final") w.wl(s"class $helperClass::ObjcProxy final")
w.wl(s": public $cppSelf") w.wl(s": public $cppSelf")
...@@ -192,21 +186,61 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) { ...@@ -192,21 +186,61 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) {
} }
} }
} }
})
}
w.wl w.wl
w.wl(s"auto $helperClass::toCpp(ObjcType objc) -> CppType") wrapNamespace(w, spec.objcppNamespace, w => {
w.braced { // ObjC-to-C++ coversion
w.wl(s"return objc ? ::djinni::DbxObjcWrapperCache<ObjcProxy>::getInstance()->get(objc) : nullptr;") w.wl(s"auto $helperClass::toCpp(ObjcType objc) -> CppType").braced {
// Handle null
w.w("if (!objc)").braced {
w.wl("return nullptr;")
}
if (i.ext.cpp && !i.ext.objc) {
// C++ only. In this case we generate a class instead of a protocol, so
// we don't have to do any casting at all, just access cppRef directly.
w.wl(s"return objc.cppRef.get();")
} else {
// ObjC only, or ObjC and C++.
val objcExtSelf = objcppMarshal.helperClass("objc_proxy")
if (i.ext.cpp) {
// If it could be implemented in C++, we might have to unwrap a proxy object.
w.w(s"if ([(id)objc isKindOfClass:[$objcSelf class]])").braced {
w.wl(s"return (($objcSelf*)objc).cppRef.get();")
}
}
w.wl(s"return ::djinni::DbxObjcWrapperCache<$objcExtSelf>::getInstance()->get(objc);")
}
} }
w.wl w.wl
w.wl(s"auto $helperClass::fromCpp(const CppType& cpp) -> ObjcType") w.wl(s"auto $helperClass::fromCpp(const CppType& cpp) -> ObjcType").braced {
w.braced { // Handle null
w.wl(s"assert(!cpp || dynamic_cast<ObjcProxy*>(cpp.get()));") w.w("if (!cpp)").braced {
w.wl(s"return cpp ? static_cast<ObjcProxy&>(*cpp).Handle::get() : nil;") w.wl("return nil;")
}
if (i.ext.objc && !i.ext.cpp) {
// ObjC only. In this case we *must* unwrap a proxy object - the dynamic_cast will
// throw bad_cast if we gave it something of the wrong type.
val objcExtSelf = objcppMarshal.helperClass("objc_proxy")
w.wl(s"return dynamic_cast<$objcExtSelf&>(*cpp).Handle::get();")
} else {
// C++ only, or C++ and ObjC.
if (i.ext.objc) {
// If it could be implemented in ObjC, we might have to unwrap a proxy object.
val objcExtSelf = objcppMarshal.helperClass("objc_proxy")
w.w(s"if (auto cppPtr = dynamic_cast<${objcExtSelf}*>(cpp.get()))").braced {
w.wl("return cppPtr->Handle::get();")
}
}
w.w(s"return ::djinni::DbxCppWrapperCache<$cppSelf>::getInstance()->get(cpp, [] (const CppType& p)").bracedEnd(");") {
w.wl(s"return [[$objcSelf alloc] initWithCpp:p];")
}
}
} }
}) })
}) })
} }
}
override def generateRecord(origin: String, ident: Ident, doc: Doc, params: Seq[TypeParam], r: Record) { override def generateRecord(origin: String, ident: Ident, doc: Doc, params: Seq[TypeParam], r: Record) {
val refs = new ObjcRefs() val refs = new ObjcRefs()
......
...@@ -25,6 +25,7 @@ test_helpers = interface +c { ...@@ -25,6 +25,7 @@ test_helpers = interface +c {
static create_cpp_token(): token; static create_cpp_token(): token;
static check_cpp_token(t: token); static check_cpp_token(t: token);
static cpp_token_id(t: token): i64; static cpp_token_id(t: token): i64;
static check_token_type(t: token, type: string);
static return_none(): optional<i32>; static return_none(): optional<i32>;
......
token = interface +c +j { token = interface +c +j +o {
whoami() : string;
} }
...@@ -63,6 +63,8 @@ public: ...@@ -63,6 +63,8 @@ public:
static int64_t cpp_token_id(const std::shared_ptr<Token> & t); static int64_t cpp_token_id(const std::shared_ptr<Token> & t);
static void check_token_type(const std::shared_ptr<Token> & t, const std::string & type);
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 */
......
...@@ -3,7 +3,11 @@ ...@@ -3,7 +3,11 @@
#pragma once #pragma once
#include <string>
class Token { class Token {
public: public:
virtual ~Token() {} virtual ~Token() {}
virtual std::string whoami() = 0;
}; };
...@@ -47,6 +47,8 @@ public abstract class TestHelpers { ...@@ -47,6 +47,8 @@ public abstract class TestHelpers {
public static native long cppTokenId(Token t); public static native long cppTokenId(Token t);
public static native void checkTokenType(Token t, String type);
public static native Integer returnNone(); public static native Integer returnNone();
/** Ensures that we generate integer translation code */ /** Ensures that we generate integer translation code */
......
...@@ -6,6 +6,7 @@ package com.dropbox.djinni.test; ...@@ -6,6 +6,7 @@ package com.dropbox.djinni.test;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
public abstract class Token { public abstract class Token {
public abstract String whoami();
public static final class CppProxy extends Token public static final class CppProxy extends Token
{ {
...@@ -29,5 +30,13 @@ public abstract class Token { ...@@ -29,5 +30,13 @@ public abstract class Token {
destroy(); destroy();
super.finalize(); super.finalize();
} }
@Override
public String whoami()
{
assert !this.destroyed.get() : "trying to use a destroyed object";
return native_whoami(this.nativeRef);
}
private native String native_whoami(long _nativeRef);
} }
} }
...@@ -202,6 +202,15 @@ CJNIEXPORT jlong JNICALL Java_com_dropbox_djinni_test_TestHelpers_cppTokenId(JNI ...@@ -202,6 +202,15 @@ CJNIEXPORT jlong JNICALL Java_com_dropbox_djinni_test_TestHelpers_cppTokenId(JNI
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */) } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
} }
CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestHelpers_checkTokenType(JNIEnv* jniEnv, jobject /*this*/, jobject j_t, jstring j_type)
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
::TestHelpers::check_token_type(::djinni_generated::NativeToken::toCpp(jniEnv, j_t),
::djinni::String::toCpp(jniEnv, j_type));
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
}
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 {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// This file generated by Djinni from token.djinni // This file generated by Djinni from token.djinni
#include "NativeToken.hpp" // my header #include "NativeToken.hpp" // my header
#include "Marshal.hpp"
namespace djinni_generated { namespace djinni_generated {
...@@ -13,6 +14,14 @@ NativeToken::JavaProxy::JavaProxy(JniType j) : JavaProxyCacheEntry(j) { } ...@@ -13,6 +14,14 @@ NativeToken::JavaProxy::JavaProxy(JniType j) : JavaProxyCacheEntry(j) { }
NativeToken::JavaProxy::~JavaProxy() = default; NativeToken::JavaProxy::~JavaProxy() = default;
std::string NativeToken::JavaProxy::whoami() {
auto jniEnv = ::djinni::jniGetThreadEnv();
::djinni::JniLocalScope jscope(jniEnv, 10);
const auto& data = ::djinni::JniClass<::djinni_generated::NativeToken>::get();
auto jret = (jstring)jniEnv->CallObjectMethod(getGlobalRef(), data.method_whoami);
::djinni::jniExceptionCheck(jniEnv);
return ::djinni::String::toCpp(jniEnv, jret);
}
CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_Token_00024CppProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef) CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_Token_00024CppProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef)
{ {
...@@ -22,4 +31,14 @@ CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_Token_00024CppProxy_nativeD ...@@ -22,4 +31,14 @@ CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_Token_00024CppProxy_nativeD
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, ) } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
} }
CJNIEXPORT jstring JNICALL Java_com_dropbox_djinni_test_Token_00024CppProxy_native_1whoami(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef)
{
try {
DJINNI_FUNCTION_PROLOGUE1(jniEnv, nativeRef);
const auto& ref = ::djinni::CppProxyHandle<::Token>::get(nativeRef);
auto r = ref->whoami();
return ::djinni::String::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
} // namespace djinni_generated } // namespace djinni_generated
...@@ -31,6 +31,7 @@ private: ...@@ -31,6 +31,7 @@ private:
JavaProxy(JniType j); JavaProxy(JniType j);
~JavaProxy(); ~JavaProxy();
std::string whoami() override;
private: private:
using ::djinni::JavaProxyCacheEntry::getGlobalRef; using ::djinni::JavaProxyCacheEntry::getGlobalRef;
...@@ -39,6 +40,7 @@ private: ...@@ -39,6 +40,7 @@ private:
}; };
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/Token") }; const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/Token") };
const jmethodID method_whoami { ::djinni::jniGetMethodID(clazz.get(), "whoami", "()Ljava/lang/String;") };
}; };
} // namespace djinni_generated } // namespace djinni_generated
...@@ -35,15 +35,24 @@ public: ...@@ -35,15 +35,24 @@ public:
} }
}; };
} // namespace djinni_generated
namespace djinni_generated {
auto ClientInterface::toCpp(ObjcType objc) -> CppType auto ClientInterface::toCpp(ObjcType objc) -> CppType
{ {
return objc ? ::djinni::DbxObjcWrapperCache<ObjcProxy>::getInstance()->get(objc) : nullptr; if (!objc) {
return nullptr;
}
return ::djinni::DbxObjcWrapperCache<ObjcProxy>::getInstance()->get(objc);
} }
auto ClientInterface::fromCpp(const CppType& cpp) -> ObjcType auto ClientInterface::fromCpp(const CppType& cpp) -> ObjcType
{ {
assert(!cpp || dynamic_cast<ObjcProxy*>(cpp.get())); if (!cpp) {
return cpp ? static_cast<ObjcProxy&>(*cpp).Handle::get() : nil; return nil;
}
return dynamic_cast<ObjcProxy&>(*cpp).Handle::get();
} }
} // namespace djinni_generated } // namespace djinni_generated
...@@ -19,23 +19,6 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th ...@@ -19,23 +19,6 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th
@end @end
namespace djinni_generated {
auto ConstantsInterface::toCpp(ObjcType objc) -> CppType
{
return objc ? objc.cppRef.get() : nullptr;
}
auto ConstantsInterface::fromCpp(const CppType& cpp) -> ObjcType
{
return !cpp ? nil : ::djinni::DbxCppWrapperCache<::ConstantsInterface>::getInstance()->get(cpp, [] (const CppType& p)
{
return [[DBConstantsInterface alloc] initWithCpp:p];
});
}
} // namespace djinni_generated
@implementation DBConstantsInterface @implementation DBConstantsInterface
- (id)initWithCpp:(const std::shared_ptr<::ConstantsInterface>&)cppRef - (id)initWithCpp:(const std::shared_ptr<::ConstantsInterface>&)cppRef
...@@ -53,3 +36,25 @@ auto ConstantsInterface::fromCpp(const CppType& cpp) -> ObjcType ...@@ -53,3 +36,25 @@ auto ConstantsInterface::fromCpp(const CppType& cpp) -> ObjcType
} }
@end @end
namespace djinni_generated {
auto ConstantsInterface::toCpp(ObjcType objc) -> CppType
{
if (!objc) {
return nullptr;
}
return objc.cppRef.get();
}
auto ConstantsInterface::fromCpp(const CppType& cpp) -> ObjcType
{
if (!cpp) {
return nil;
}
return ::djinni::DbxCppWrapperCache<::ConstantsInterface>::getInstance()->get(cpp, [] (const CppType& p) {
return [[DBConstantsInterface alloc] initWithCpp:p];
});
}
} // namespace djinni_generated
...@@ -20,23 +20,6 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th ...@@ -20,23 +20,6 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th
@end @end
namespace djinni_generated {
auto CppException::toCpp(ObjcType objc) -> CppType
{
return objc ? objc.cppRef.get() : nullptr;
}
auto CppException::fromCpp(const CppType& cpp) -> ObjcType
{
return !cpp ? nil : ::djinni::DbxCppWrapperCache<::CppException>::getInstance()->get(cpp, [] (const CppType& p)
{
return [[DBCppException alloc] initWithCpp:p];
});
}
} // namespace djinni_generated
@implementation DBCppException @implementation DBCppException
- (id)initWithCpp:(const std::shared_ptr<::CppException>&)cppRef - (id)initWithCpp:(const std::shared_ptr<::CppException>&)cppRef
...@@ -62,3 +45,25 @@ auto CppException::fromCpp(const CppType& cpp) -> ObjcType ...@@ -62,3 +45,25 @@ auto CppException::fromCpp(const CppType& cpp) -> ObjcType
} }
@end @end
namespace djinni_generated {
auto CppException::toCpp(ObjcType objc) -> CppType
{
if (!objc) {
return nullptr;
}
return objc.cppRef.get();
}
auto CppException::fromCpp(const CppType& cpp) -> ObjcType
{
if (!cpp) {
return nil;
}
return ::djinni::DbxCppWrapperCache<::CppException>::getInstance()->get(cpp, [] (const CppType& p) {
return [[DBCppException alloc] initWithCpp:p];
});
}
} // namespace djinni_generated
...@@ -26,23 +26,6 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th ...@@ -26,23 +26,6 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th
@end @end
namespace djinni_generated {
auto TestHelpers::toCpp(ObjcType objc) -> CppType
{
return objc ? objc.cppRef.get() : nullptr;
}
auto TestHelpers::fromCpp(const CppType& cpp) -> ObjcType
{
return !cpp ? nil : ::djinni::DbxCppWrapperCache<::TestHelpers>::getInstance()->get(cpp, [] (const CppType& p)
{
return [[DBTestHelpers alloc] initWithCpp:p];
});
}
} // namespace djinni_generated
@implementation DBTestHelpers @implementation DBTestHelpers
- (id)initWithCpp:(const std::shared_ptr<::TestHelpers>&)cppRef - (id)initWithCpp:(const std::shared_ptr<::TestHelpers>&)cppRef
...@@ -161,33 +144,41 @@ auto TestHelpers::fromCpp(const CppType& cpp) -> ObjcType ...@@ -161,33 +144,41 @@ auto TestHelpers::fromCpp(const CppType& cpp) -> ObjcType
} DJINNI_TRANSLATE_EXCEPTIONS() } DJINNI_TRANSLATE_EXCEPTIONS()
} }
+ (nullable DBToken *)tokenId:(nullable DBToken *)t { + (nullable id<DBToken>)tokenId:(nullable id<DBToken>)t {
try { try {
auto r = ::TestHelpers::token_id(::djinni_generated::Token::toCpp(t)); auto r = ::TestHelpers::token_id(::djinni_generated::Token::toCpp(t));
return ::djinni_generated::Token::fromCpp(r); return ::djinni_generated::Token::fromCpp(r);
} DJINNI_TRANSLATE_EXCEPTIONS() } DJINNI_TRANSLATE_EXCEPTIONS()
} }
+ (nullable DBToken *)createCppToken { + (nullable id<DBToken>)createCppToken {
try { try {
auto r = ::TestHelpers::create_cpp_token(); auto r = ::TestHelpers::create_cpp_token();
return ::djinni_generated::Token::fromCpp(r); return ::djinni_generated::Token::fromCpp(r);
} DJINNI_TRANSLATE_EXCEPTIONS() } DJINNI_TRANSLATE_EXCEPTIONS()
} }
+ (void)checkCppToken:(nullable DBToken *)t { + (void)checkCppToken:(nullable id<DBToken>)t {
try { try {
::TestHelpers::check_cpp_token(::djinni_generated::Token::toCpp(t)); ::TestHelpers::check_cpp_token(::djinni_generated::Token::toCpp(t));
} DJINNI_TRANSLATE_EXCEPTIONS() } DJINNI_TRANSLATE_EXCEPTIONS()
} }
+ (int64_t)cppTokenId:(nullable DBToken *)t { + (int64_t)cppTokenId:(nullable id<DBToken>)t {
try { try {
auto r = ::TestHelpers::cpp_token_id(::djinni_generated::Token::toCpp(t)); auto r = ::TestHelpers::cpp_token_id(::djinni_generated::Token::toCpp(t));
return ::djinni::I64::fromCpp(r); return ::djinni::I64::fromCpp(r);
} DJINNI_TRANSLATE_EXCEPTIONS() } DJINNI_TRANSLATE_EXCEPTIONS()
} }
+ (void)checkTokenType:(nullable id<DBToken>)t
type:(nonnull NSString *)type {
try {
::TestHelpers::check_token_type(::djinni_generated::Token::toCpp(t),
::djinni::String::toCpp(type));
} DJINNI_TRANSLATE_EXCEPTIONS()
}
+ (nullable NSNumber *)returnNone { + (nullable NSNumber *)returnNone {
try { try {
auto r = ::TestHelpers::return_none(); auto r = ::TestHelpers::return_none();
...@@ -210,3 +201,25 @@ auto TestHelpers::fromCpp(const CppType& cpp) -> ObjcType ...@@ -210,3 +201,25 @@ auto TestHelpers::fromCpp(const CppType& cpp) -> ObjcType
} }
@end @end
namespace djinni_generated {
auto TestHelpers::toCpp(ObjcType objc) -> CppType
{
if (!objc) {
return nullptr;
}
return objc.cppRef.get();
}
auto TestHelpers::fromCpp(const CppType& cpp) -> ObjcType
{
if (!cpp) {
return nil;
}
return ::djinni::DbxCppWrapperCache<::TestHelpers>::getInstance()->get(cpp, [] (const CppType& p) {
return [[DBTestHelpers alloc] initWithCpp:p];
});
}
} // namespace djinni_generated
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
#import "DBPrimitiveList.h" #import "DBPrimitiveList.h"
#import "DBSetRecord.h" #import "DBSetRecord.h"
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@class DBToken;
@protocol DBClientInterface; @protocol DBClientInterface;
@protocol DBToken;
@interface DBTestHelpers : NSObject @interface DBTestHelpers : NSObject
...@@ -46,13 +46,16 @@ ...@@ -46,13 +46,16 @@
+ (void)checkEnum:(DBColor)c; + (void)checkEnum:(DBColor)c;
+ (nullable DBToken *)tokenId:(nullable DBToken *)t; + (nullable id<DBToken>)tokenId:(nullable id<DBToken>)t;
+ (nullable DBToken *)createCppToken; + (nullable id<DBToken>)createCppToken;
+ (void)checkCppToken:(nullable DBToken *)t; + (void)checkCppToken:(nullable id<DBToken>)t;
+ (int64_t)cppTokenId:(nullable DBToken *)t; + (int64_t)cppTokenId:(nullable id<DBToken>)t;
+ (void)checkTokenType:(nullable id<DBToken>)t
type:(nonnull NSString *)type;
+ (nullable NSNumber *)returnNone; + (nullable NSNumber *)returnNone;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file"); static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file");
@class DBToken; @protocol DBToken;
namespace djinni_generated { namespace djinni_generated {
...@@ -14,7 +14,7 @@ class Token ...@@ -14,7 +14,7 @@ class Token
{ {
public: public:
using CppType = std::shared_ptr<::Token>; using CppType = std::shared_ptr<::Token>;
using ObjcType = DBToken*; using ObjcType = id<DBToken>;
using Boxed = Token; using Boxed = Token;
......
...@@ -5,12 +5,14 @@ ...@@ -5,12 +5,14 @@
#import "DBToken.h" #import "DBToken.h"
#import "DJICppWrapperCache+Private.h" #import "DJICppWrapperCache+Private.h"
#import "DJIError.h" #import "DJIError.h"
#import "DJIMarshal+Private.h"
#import "DJIObjcWrapperCache+Private.h"
#include <exception> #include <exception>
#include <utility> #include <utility>
static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file"); static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file");
@interface DBToken () @interface DBTokenCppProxy : NSObject<DBToken>
@property (nonatomic, readonly) ::djinni::DbxCppWrapperCache<::Token>::Handle cppRef; @property (nonatomic, readonly) ::djinni::DbxCppWrapperCache<::Token>::Handle cppRef;
...@@ -18,31 +20,68 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th ...@@ -18,31 +20,68 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th
@end @end
namespace djinni_generated { @implementation DBTokenCppProxy
auto Token::toCpp(ObjcType objc) -> CppType - (id)initWithCpp:(const std::shared_ptr<::Token>&)cppRef
{ {
return objc ? objc.cppRef.get() : nullptr; if (self = [super init]) {
_cppRef.assign(cppRef);
}
return self;
} }
auto Token::fromCpp(const CppType& cpp) -> ObjcType - (nonnull NSString *)whoami {
try {
auto r = _cppRef.get()->whoami();
return ::djinni::String::fromCpp(r);
} DJINNI_TRANSLATE_EXCEPTIONS()
}
@end
namespace djinni_generated {
class Token::ObjcProxy final
: public ::Token
, public ::djinni::DbxObjcWrapperCache<ObjcProxy>::Handle
{ {
return !cpp ? nil : ::djinni::DbxCppWrapperCache<::Token>::getInstance()->get(cpp, [] (const CppType& p) public:
using Handle::Handle;
std::string whoami() override
{ {
return [[DBToken alloc] initWithCpp:p]; @autoreleasepool {
}); auto r = [Handle::get() whoami];
} return ::djinni::String::toCpp(r);
}
}
};
} // namespace djinni_generated } // namespace djinni_generated
@implementation DBToken namespace djinni_generated {
- (id)initWithCpp:(const std::shared_ptr<::Token>&)cppRef auto Token::toCpp(ObjcType objc) -> CppType
{ {
if (self = [super init]) { if (!objc) {
_cppRef.assign(cppRef); return nullptr;
} }
return self; if ([(id)objc isKindOfClass:[DBTokenCppProxy class]]) {
return ((DBTokenCppProxy*)objc).cppRef.get();
}
return ::djinni::DbxObjcWrapperCache<ObjcProxy>::getInstance()->get(objc);
} }
@end auto Token::fromCpp(const CppType& cpp) -> ObjcType
{
if (!cpp) {
return nil;
}
if (auto cppPtr = dynamic_cast<ObjcProxy*>(cpp.get())) {
return cppPtr->Handle::get();
}
return ::djinni::DbxCppWrapperCache<::Token>::getInstance()->get(cpp, [] (const CppType& p) {
return [[DBTokenCppProxy alloc] initWithCpp:p];
});
}
} // namespace djinni_generated
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@interface DBToken : NSObject @protocol DBToken
- (nonnull NSString *)whoami;
@end @end
...@@ -90,7 +90,9 @@ std::shared_ptr<Token> TestHelpers::token_id(const std::shared_ptr<Token> & in) ...@@ -90,7 +90,9 @@ std::shared_ptr<Token> TestHelpers::token_id(const std::shared_ptr<Token> & in)
return in; return in;
} }
class CppToken : public Token {}; class CppToken : public Token {
std::string whoami() { return "C++"; }
};
std::shared_ptr<Token> TestHelpers::create_cpp_token() { std::shared_ptr<Token> TestHelpers::create_cpp_token() {
return std::make_shared<CppToken>(); return std::make_shared<CppToken>();
...@@ -105,6 +107,12 @@ int64_t TestHelpers::cpp_token_id(const std::shared_ptr<Token> & in) { ...@@ -105,6 +107,12 @@ int64_t TestHelpers::cpp_token_id(const std::shared_ptr<Token> & in) {
return reinterpret_cast<int64_t>(in.get()); return reinterpret_cast<int64_t>(in.get());
} }
void TestHelpers::check_token_type(const std::shared_ptr<Token> &t, const std::string & type) {
if (t->whoami() != type) {
throw std::invalid_argument("wrong token type");
}
}
std::experimental::optional<int32_t> TestHelpers::return_none() { std::experimental::optional<int32_t> TestHelpers::return_none() {
return {}; return {};
} }
......
...@@ -5,6 +5,7 @@ import junit.framework.TestCase; ...@@ -5,6 +5,7 @@ import junit.framework.TestCase;
public class TokenTest extends TestCase { public class TokenTest extends TestCase {
private class JavaToken extends Token { private class JavaToken extends Token {
public String whoami() { return "Java"; }
} }
@Override @Override
...@@ -29,6 +30,25 @@ public class TokenTest extends TestCase { ...@@ -29,6 +30,25 @@ public class TokenTest extends TestCase {
System.runFinalization(); System.runFinalization();
} }
public void testTokenType() {
TestHelpers.checkTokenType(new JavaToken(), "Java");
TestHelpers.checkTokenType(TestHelpers.createCppToken(), "C++");
boolean threw = false;
try {
TestHelpers.checkTokenType(new JavaToken(), "foo");
} catch (RuntimeException e) {
threw = true;
}
assertTrue(threw);
threw = false;
try {
TestHelpers.checkTokenType(TestHelpers.createCppToken(), "foo");
} catch (RuntimeException e) {
threw = true;
}
assertTrue(threw);
}
public void testNotCppToken() { public void testNotCppToken() {
boolean threw = false; boolean threw = false;
try { try {
......
#import "DBTestHelpers.h"
#import "DBToken.h"
#import <XCTest/XCTest.h>
@interface DBTokenTests : XCTestCase
@end
@interface DBObjcToken : NSObject<DBToken>
- (NSString *)whoami;
@end
@implementation DBObjcToken
- (NSString *)whoami {
return @"ObjC";
}
@end
@implementation DBTokenTests
- (void)setUp
{
[super setUp];
}
- (void)tearDown
{
[super tearDown];
}
- (void)testTokens
{
id<DBToken> t = [[DBObjcToken alloc] init];
XCTAssertEqual([DBTestHelpers tokenId:t], t);
}
- (void)testNullToken
{
XCTAssertNil([DBTestHelpers tokenId:nil]);
}
- (void)testTokenType
{
[DBTestHelpers checkTokenType:[[DBObjcToken alloc] init] type:@"ObjC"];
[DBTestHelpers checkTokenType:[DBTestHelpers createCppToken] type:@"C++"];
XCTAssertThrows([DBTestHelpers checkTokenType:[[DBObjcToken alloc] init] type:@"foo"]);
XCTAssertThrows([DBTestHelpers checkTokenType:[DBTestHelpers createCppToken] type:@"foo"]);
}
- (void)testCppToken
{
id<DBToken> ct = [DBTestHelpers createCppToken];
XCTAssertEqual([DBTestHelpers tokenId:ct], ct);
[DBTestHelpers checkCppToken:ct];
ct = nil;
}
- (void)testNotCppToken {
XCTAssertThrows([DBTestHelpers checkCppToken:[[DBObjcToken alloc] init]]);
}
@end
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
65868B5F1989FE4200D60EEE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65868B5E1989FE4200D60EEE /* UIKit.framework */; }; 65868B5F1989FE4200D60EEE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65868B5E1989FE4200D60EEE /* UIKit.framework */; };
65868B621989FE4200D60EEE /* libDjinniObjcTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 65868B4A1989FE4200D60EEE /* libDjinniObjcTest.a */; }; 65868B621989FE4200D60EEE /* libDjinniObjcTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 65868B4A1989FE4200D60EEE /* libDjinniObjcTest.a */; };
6D66A8A91A3B09F000B312E8 /* DBConstantTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D66A8A81A3B09F000B312E8 /* DBConstantTests.mm */; }; 6D66A8A91A3B09F000B312E8 /* DBConstantTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D66A8A81A3B09F000B312E8 /* DBConstantTests.mm */; };
A20094101B06982F00EF8D9B /* DBTokenTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = A200940E1B0697D300EF8D9B /* DBTokenTests.mm */; };
A238CA8C1AF84B7100CDDCE5 /* DBAssortedIntegers+Private.mm in Sources */ = {isa = PBXBuildFile; fileRef = A238CA741AF84B7100CDDCE5 /* DBAssortedIntegers+Private.mm */; }; A238CA8C1AF84B7100CDDCE5 /* DBAssortedIntegers+Private.mm in Sources */ = {isa = PBXBuildFile; fileRef = A238CA741AF84B7100CDDCE5 /* DBAssortedIntegers+Private.mm */; };
A238CA8E1AF84B7100CDDCE5 /* DBClientReturnedRecord+Private.mm in Sources */ = {isa = PBXBuildFile; fileRef = A238CA761AF84B7100CDDCE5 /* DBClientReturnedRecord+Private.mm */; }; A238CA8E1AF84B7100CDDCE5 /* DBClientReturnedRecord+Private.mm in Sources */ = {isa = PBXBuildFile; fileRef = A238CA761AF84B7100CDDCE5 /* DBClientReturnedRecord+Private.mm */; };
A238CA901AF84B7100CDDCE5 /* DBConstants+Private.mm in Sources */ = {isa = PBXBuildFile; fileRef = A238CA781AF84B7100CDDCE5 /* DBConstants+Private.mm */; }; A238CA901AF84B7100CDDCE5 /* DBConstants+Private.mm in Sources */ = {isa = PBXBuildFile; fileRef = A238CA781AF84B7100CDDCE5 /* DBConstants+Private.mm */; };
...@@ -118,6 +119,7 @@ ...@@ -118,6 +119,7 @@
65868B5B1989FE4200D60EEE /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 65868B5B1989FE4200D60EEE /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
65868B5E1989FE4200D60EEE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 65868B5E1989FE4200D60EEE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
6D66A8A81A3B09F000B312E8 /* DBConstantTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DBConstantTests.mm; sourceTree = "<group>"; }; 6D66A8A81A3B09F000B312E8 /* DBConstantTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DBConstantTests.mm; sourceTree = "<group>"; };
A200940E1B0697D300EF8D9B /* DBTokenTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DBTokenTests.mm; sourceTree = "<group>"; };
A238CA741AF84B7100CDDCE5 /* DBAssortedIntegers+Private.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "DBAssortedIntegers+Private.mm"; sourceTree = "<group>"; }; A238CA741AF84B7100CDDCE5 /* DBAssortedIntegers+Private.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "DBAssortedIntegers+Private.mm"; sourceTree = "<group>"; };
A238CA761AF84B7100CDDCE5 /* DBClientReturnedRecord+Private.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "DBClientReturnedRecord+Private.mm"; sourceTree = "<group>"; }; A238CA761AF84B7100CDDCE5 /* DBClientReturnedRecord+Private.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "DBClientReturnedRecord+Private.mm"; sourceTree = "<group>"; };
A238CA781AF84B7100CDDCE5 /* DBConstants+Private.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "DBConstants+Private.mm"; sourceTree = "<group>"; }; A238CA781AF84B7100CDDCE5 /* DBConstants+Private.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "DBConstants+Private.mm"; sourceTree = "<group>"; };
...@@ -273,6 +275,7 @@ ...@@ -273,6 +275,7 @@
6536CD7919A6C99800DD7715 /* Tests */ = { 6536CD7919A6C99800DD7715 /* Tests */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A200940E1B0697D300EF8D9B /* DBTokenTests.mm */,
6536CD7A19A6C99800DD7715 /* DBClientInterfaceTests.mm */, 6536CD7A19A6C99800DD7715 /* DBClientInterfaceTests.mm */,
6536CD7B19A6C99800DD7715 /* DBCppExceptionTests.mm */, 6536CD7B19A6C99800DD7715 /* DBCppExceptionTests.mm */,
6536CD7C19A6C99800DD7715 /* DBMapRecordTests.mm */, 6536CD7C19A6C99800DD7715 /* DBMapRecordTests.mm */,
...@@ -568,6 +571,7 @@ ...@@ -568,6 +571,7 @@
CFFD58B21B041BD9001E10B6 /* DBConstantsInterface.mm in Sources */, CFFD58B21B041BD9001E10B6 /* DBConstantsInterface.mm in Sources */,
6536CD9319A6C9A800DD7715 /* DBRecordWithDerivingsObjcTests.mm in Sources */, 6536CD9319A6C9A800DD7715 /* DBRecordWithDerivingsObjcTests.mm in Sources */,
6536CD9019A6C9A800DD7715 /* DBNestedCollectionTests.mm in Sources */, 6536CD9019A6C9A800DD7715 /* DBNestedCollectionTests.mm in Sources */,
A20094101B06982F00EF8D9B /* DBTokenTests.mm in Sources */,
6536CD8F19A6C9A800DD7715 /* DBMapRecordTests.mm in Sources */, 6536CD8F19A6C9A800DD7715 /* DBMapRecordTests.mm in Sources */,
6536CD9419A6C9A800DD7715 /* DBSetRecordTests.mm in Sources */, 6536CD9419A6C9A800DD7715 /* DBSetRecordTests.mm 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