Commit b22615ae authored by Jacob Potter's avatar Jacob Potter

Merge branch 'master' into bidirectional-interfaces

parents f0aec36d 1734c72e
......@@ -10,8 +10,10 @@ clean:
-xcodebuild -workspace example/objc/TextSort.xcworkspace -scheme TextSort -configuration 'Debug' -sdk iphonesimulator clean
# rule to lazily clone gyp
# freeze gyp at the last version with android support
./deps/gyp:
git clone --depth 1 https://chromium.googlesource.com/external/gyp.git ./deps/gyp
git clone https://chromium.googlesource.com/external/gyp.git ./deps/gyp
cd deps/gyp && git checkout -q 0bb67471bca068996e15b56738fa4824dfa19de0
# we specify a root target for android to prevent all of the targets from spidering out
GypAndroid.mk: ./deps/gyp example/libtextsort.gyp support-lib/support_lib.gyp example/example.djinni
......
......@@ -19,6 +19,7 @@ auto NativeItemList::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::Loca
}
auto NativeItemList::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 2);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeItemList>::get();
return {::djinni::List<::djinni::String>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mItems))};
......
......@@ -148,7 +148,7 @@ class JNIGenerator(spec: Spec) extends Generator(spec) {
w.wl
writeJniTypeParams(w, params)
w.w(s"auto $jniHelperWithParams::toCpp(JNIEnv* jniEnv, JniType j) -> CppType").braced {
//w.wl(s"::${spec.jniNamespace}::JniLocalScope jscope(jniEnv, 10);")
w.wl(s"::djinni::JniLocalScope jscope(jniEnv, ${r.fields.size + 1});")
w.wl(s"assert(j != nullptr);")
if(r.fields.isEmpty)
w.wl("(void)j; // Suppress warnings in release builds for empty records")
......
......@@ -151,12 +151,39 @@ namespace djinni
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)};
assert(j != nullptr);
std::vector<uint8_t> ret;
jsize length = jniEnv->GetArrayLength(j);
jniExceptionCheck(jniEnv);
if (!length) {
return {};
}
{
auto deleter = [jniEnv, j] (void* c) {
if (c) {
jniEnv->ReleasePrimitiveArrayCritical(j, c, JNI_ABORT);
}
};
std::unique_ptr<uint8_t, decltype(deleter)> ptr(
reinterpret_cast<uint8_t*>(jniEnv->GetPrimitiveArrayCritical(j, nullptr)),
deleter
);
if (ptr) {
// Construct and then move-assign. This copies the elements only once,
// and avoids having to initialize before filling (as with resize())
ret = std::vector<uint8_t>{ptr.get(), ptr.get() + length};
} else {
// Something failed...
jniExceptionCheck(jniEnv);
}
}
return ret;
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
......
......@@ -16,7 +16,6 @@
// This header can only be imported to Objective-C++ source code!
#import "DJIWeakPtrWrapper+Private.h"
#import <Foundation/Foundation.h>
#include <memory>
#include <mutex>
......@@ -37,9 +36,9 @@ public:
std::shared_ptr<T> get(id objcRef) {
std::unique_lock<std::mutex> lock(m_mutex);
std::shared_ptr<T> ret;
DBWeakPtrWrapper *wrapper = [m_mapping objectForKey:objcRef];
if (wrapper != nil) {
ret = std::static_pointer_cast<T>(wrapper.ptr.lock());
auto it = m_mapping.find((__bridge void*)objcRef);
if (it != m_mapping.end()) {
ret = std::static_pointer_cast<T>(it->second.lock());
if (ret == nullptr) {
ret = new_wrapper(objcRef);
}
......@@ -51,10 +50,7 @@ public:
void remove(id objcRef) {
std::unique_lock<std::mutex> lock(m_mutex);
DBWeakPtrWrapper *wrapper = [m_mapping objectForKey:objcRef];
if (wrapper.ptr.expired()) {
[m_mapping removeObjectForKey:objcRef];
}
m_mapping.erase((__bridge void*)objcRef);
}
class Handle {
......@@ -74,18 +70,13 @@ public:
private:
NSMapTable *m_mapping;
std::unordered_map<void*, std::weak_ptr<void>> m_mapping;
std::mutex m_mutex;
DbxObjcWrapperCache() {
m_mapping = [NSMapTable weakToStrongObjectsMapTable];
}
std::shared_ptr<T> new_wrapper(id objcRef) {
std::shared_ptr<T> ret = std::make_shared<T>(objcRef);
std::weak_ptr<void> ptr(std::static_pointer_cast<void>(ret));
DBWeakPtrWrapper *wrapper = [[DBWeakPtrWrapper alloc] initWithWeakPtr:ptr];
[m_mapping setObject:wrapper forKey:objcRef];
m_mapping[(__bridge void*)objcRef] = ptr;
return ret;
}
......
......@@ -31,4 +31,6 @@ test_helpers = interface +c {
# Ensures that we generate integer translation code
static assorted_integers_id(i: assorted_integers): assorted_integers;
static id_binary(b: binary): binary;
}
......@@ -14,6 +14,7 @@
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
class ClientInterface;
class Token;
......@@ -68,4 +69,6 @@ public:
/** Ensures that we generate integer translation code */
static AssortedIntegers assorted_integers_id(const AssortedIntegers & i);
static std::vector<uint8_t> id_binary(const std::vector<uint8_t> & b);
};
......@@ -54,6 +54,8 @@ public abstract class TestHelpers {
/** Ensures that we generate integer translation code */
public static native AssortedIntegers assortedIntegersId(AssortedIntegers i);
public static native byte[] idBinary(byte[] b);
public static final class CppProxy extends TestHelpers
{
private final long nativeRef;
......
......@@ -26,6 +26,7 @@ auto NativeAssortedIntegers::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djin
}
auto NativeAssortedIntegers::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 9);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeAssortedIntegers>::get();
return {::djinni::I8::toCpp(jniEnv, jniEnv->GetByteField(j, data.field_mEight)),
......
......@@ -21,6 +21,7 @@ auto NativeClientReturnedRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::
}
auto NativeClientReturnedRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 4);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeClientReturnedRecord>::get();
return {::djinni::I64::toCpp(jniEnv, jniEnv->GetLongField(j, data.field_mRecordId)),
......
......@@ -20,6 +20,7 @@ auto NativeConstants::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::Loc
}
auto NativeConstants::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 3);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeConstants>::get();
return {::djinni::I32::toCpp(jniEnv, jniEnv->GetIntField(j, data.field_mSomeInteger)),
......
......@@ -19,6 +19,7 @@ auto NativeDateRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::Lo
}
auto NativeDateRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 2);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeDateRecord>::get();
return {::djinni::Date::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mCreatedAt))};
......
......@@ -19,6 +19,7 @@ auto NativeMapDateRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni:
}
auto NativeMapDateRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 2);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeMapDateRecord>::get();
return {::djinni::Map<::djinni::String, ::djinni::Date>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mDatesById))};
......
......@@ -19,6 +19,7 @@ auto NativeMapListRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni:
}
auto NativeMapListRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 2);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeMapListRecord>::get();
return {::djinni::List<::djinni::Map<::djinni::String, ::djinni::I64>>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mMapList))};
......
......@@ -19,6 +19,7 @@ auto NativeMapRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::Loc
}
auto NativeMapRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 2);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeMapRecord>::get();
return {::djinni::Map<::djinni::String, ::djinni::I64>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mMap))};
......
......@@ -19,6 +19,7 @@ auto NativeNestedCollection::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djin
}
auto NativeNestedCollection::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 2);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeNestedCollection>::get();
return {::djinni::List<::djinni::Set<::djinni::String>>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mSetList))};
......
......@@ -19,6 +19,7 @@ auto NativePrimitiveList::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni:
}
auto NativePrimitiveList::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 2);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativePrimitiveList>::get();
return {::djinni::List<::djinni::I64>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mList))};
......
......@@ -20,6 +20,7 @@ auto NativeRecordWithDerivings::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::d
}
auto NativeRecordWithDerivings::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 3);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeRecordWithDerivings>::get();
return {::djinni::I32::toCpp(jniEnv, jniEnv->GetIntField(j, data.field_mKey1)),
......
......@@ -21,6 +21,7 @@ auto NativeRecordWithNestedDerivings::fromCpp(JNIEnv* jniEnv, const CppType& c)
}
auto NativeRecordWithNestedDerivings::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 3);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeRecordWithNestedDerivings>::get();
return {::djinni::I32::toCpp(jniEnv, jniEnv->GetIntField(j, data.field_mKey)),
......
......@@ -19,6 +19,7 @@ auto NativeSetRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::Loc
}
auto NativeSetRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 2);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeSetRecord>::get();
return {::djinni::Set<::djinni::String>::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_mSet))};
......
......@@ -229,4 +229,13 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_assortedInte
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
CJNIEXPORT jbyteArray JNICALL Java_com_dropbox_djinni_test_TestHelpers_idBinary(JNIEnv* jniEnv, jobject /*this*/, jbyteArray j_b)
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
auto r = ::TestHelpers::id_binary(::djinni::Binary::toCpp(jniEnv, j_b));
return ::djinni::Binary::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
} // namespace djinni_generated
......@@ -193,6 +193,13 @@ static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for th
} DJINNI_TRANSLATE_EXCEPTIONS()
}
+ (nonnull NSData *)idBinary:(nonnull NSData *)b {
try {
auto r = ::TestHelpers::id_binary(::djinni::Binary::toCpp(b));
return ::djinni::Binary::fromCpp(r);
} DJINNI_TRANSLATE_EXCEPTIONS()
}
@end
namespace djinni_generated {
......
......@@ -62,4 +62,6 @@
/** Ensures that we generate integer translation code */
+ (nonnull DBAssortedIntegers *)assortedIntegersId:(nonnull DBAssortedIntegers *)i;
+ (nonnull NSData *)idBinary:(nonnull NSData *)b;
@end
......@@ -138,3 +138,7 @@ void TestHelpers::check_enum(color) {} // stub
AssortedIntegers TestHelpers::assorted_integers_id(const AssortedIntegers & i) {
return i;
}
std::vector<uint8_t> TestHelpers::id_binary(const std::vector<uint8_t> & v) {
return v;
}
......@@ -3,6 +3,7 @@ package com.dropbox.djinni.test;
import junit.framework.TestCase;
import java.util.ArrayList;
import java.util.Arrays;
public class PrimitiveListTest extends TestCase {
......@@ -27,4 +28,10 @@ public class PrimitiveListTest extends TestCase {
PrimitiveList converted = TestHelpers.getPrimitiveList();
assertEquals(converted.getList(), jPrimitiveList.getList());
}
public void testBinary()
{
byte[] b = { 1, 2, 3 };
assertTrue(Arrays.equals(TestHelpers.idBinary(b), b));
}
}
......@@ -11,8 +11,9 @@
<src path="../generated-src"/>
<src path="../handwritten-src"/>
</javac>
<java classname="org.junit.runner.JUnitCore">
<java classname="org.junit.runner.JUnitCore" fork="true">
<classpath path="hamcrest-core-1.3.jar:junit-4.11.jar:classes"/>
<jvmarg value="-Xcheck:jni"/>
<arg value="com.dropbox.djinni.test.AllTests"/>
</java>
</target>
......
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