diff --git a/BUILD b/BUILD index daced34..0fd58f0 100644 --- a/BUILD +++ b/BUILD @@ -49,6 +49,7 @@ cc_library( "//implementation:global_string", "//implementation:id", "//implementation:id_type", + "//implementation:inheritance", "//implementation:jni_type", "//implementation:jvm", "//implementation:jvm_ref", diff --git a/implementation/BUILD b/implementation/BUILD index e570ee7..b5957d4 100644 --- a/implementation/BUILD +++ b/implementation/BUILD @@ -438,6 +438,28 @@ cc_library( ], ) +################################################################################ +# Inheritance. +################################################################################ +cc_library( + name = "inheritance", + hdrs = ["inheritance.h"], + deps = [ + ":id_type", + ], +) + +cc_test( + name = "inheritance_test", + srcs = ["inheritance_test.cc"], + deps = [ + "//:jni_bind", + "//:jni_test", + "//testing/base/public:gunit_for_library", + "@googletest//:gtest_main", + ], +) + ################################################################################ # LocalArray. ################################################################################ @@ -920,6 +942,7 @@ cc_library( ":id_type", ":jni_type", ":method_selection", + ":no_class_specified", ":no_idx", ":ref_base", "//:jni_dep", diff --git a/implementation/inheritance.h b/implementation/inheritance.h new file mode 100644 index 0000000..4dce163 --- /dev/null +++ b/implementation/inheritance.h @@ -0,0 +1,46 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JNI_BIND_IMPLEMENTATION_INHERITANCE_H_ +#define JNI_BIND_IMPLEMENTATION_INHERITANCE_H_ + +// IWYU pragma: private, include "third_party/jni_wrapper/jni_bind.h" + +#include + +#include "implementation/id_type.h" + +namespace jni { + +struct Inheritance { + template + struct Helper { + static_assert(false, + "You must use an overload set or field for `Inheritance`."); + }; + + template + struct Helper> { + using type = void; + }; + + template + using type = typename Helper::type; +}; + +} // namespace jni + +#endif // JNI_BIND_IMPLEMENTATION_INHERITANCE_H_ diff --git a/implementation/inheritance_test.cc b/implementation/inheritance_test.cc new file mode 100644 index 0000000..ca3179f --- /dev/null +++ b/implementation/inheritance_test.cc @@ -0,0 +1,24 @@ +#include +#include +#include "jni_bind.h" +#include "jni_test.h" + +namespace { + +using ::jni::test::JniTest; + +constexpr jni::Class c1{ + "c1", jni::Method{"Foo", jni::Return{}, jni::Params{}}}; + +constexpr jni::Class c2{ + "c2", jni::Extends{c1}, + jni::Method{"Bar", jni::Return{}, jni::Params{}}}; + +TEST_F(JniTest, Inhertance_CallsSuper) { + // jni::LocalObject local_object{}; + // jni::LocalObject local_object{}; + // local_object("Bar", 123); + // local_object("Foo", 123); +} + +} // namespace diff --git a/implementation/jni_type.h b/implementation/jni_type.h index 5a33be9..45cf01e 100644 --- a/implementation/jni_type.h +++ b/implementation/jni_type.h @@ -55,6 +55,8 @@ struct JniT, RootObject>>> { + static constexpr bool kIsRoot = false; + static constexpr std::size_t kRank = kRank_; static_assert(kRank != -1); diff --git a/implementation/jni_type_test.cc b/implementation/jni_type_test.cc index df2d2d7..d78ce5b 100644 --- a/implementation/jni_type_test.cc +++ b/implementation/jni_type_test.cc @@ -159,12 +159,24 @@ using GrandparentJniT = JniT; using ParentJniT = JniT; using ChildJniT = JniT; +static_assert(GrandparentJniT::ParentJniT::kIsRoot); +static_assert(!GrandparentJniT::kIsRoot); +static_assert(!ParentJniT::kIsRoot); +static_assert(!ChildJniT::kIsRoot); + +static_assert(JniTEqual_v); +static_assert(JniTEqual_v); +static_assert(JniTEqual_v); + +// Why const differs on localstring? static_assert( std::is_same_v); +static_assert(!JniT::kIsRoot); +static_assert(JniT::ParentJniT::kIsRoot); + static_assert( std::is_same_v, jni::RootObject>); -; static_assert(GrandparentJniT::kDepthInAncestors == 0); static_assert(ParentJniT::kDepthInAncestors == 1); diff --git a/implementation/object_ref.h b/implementation/object_ref.h index e3fef71..0dee6e2 100644 --- a/implementation/object_ref.h +++ b/implementation/object_ref.h @@ -30,6 +30,7 @@ #include "implementation/jni_helper/lifecycle.h" #include "implementation/jni_type.h" #include "implementation/method_selection.h" +#include "implementation/no_class_specified.h" #include "implementation/no_idx.h" #include "implementation/ref_base.h" #include "jni_dep.h" @@ -39,6 +40,34 @@ namespace jni { +template +class ObjectRef; + +template +struct InheritanceProxy; + +// non root +template +struct InheritanceProxy> { + static_assert(std::is_same_v); + using type = ObjectRef; + // using type = RootObject; +}; + +// root +template +struct InheritanceProxy> { + static_assert(std::is_same_v); + using type = RefBase; +}; + +template +class ObjectRef; + // Represents a runtime instance of a JNI Object. Instead of using this class // directly, instead the more specialised types such as LocalObject, // GlobalObject, etc. @@ -53,7 +82,13 @@ class ObjectRef public metaprogramming::QueryableMap_t< ObjectRef, JniT::stripped_class_v, &JniT::ClassT::fields_>, public RefBase { + // public InheritanceProxy::type { protected: + static_assert(std::is_same_v || + // std::is_same_v< typename JniT::ParentJniT::StorageType, + // jobject> std::is_same_v< void, typename JniT::ParentJniT> + std::is_same_v); + static_assert( JniT::class_loader_v .template SupportedDirectlyOrIndirectly(), diff --git a/implementation/ref_base.h b/implementation/ref_base.h index 6bbcc63..29eb79a 100644 --- a/implementation/ref_base.h +++ b/implementation/ref_base.h @@ -59,7 +59,7 @@ class RefBase : public RefBaseBase { explicit operator StorageType() const { return object_ref_; } - protected: + // protected: StorageType object_ref_ = nullptr; }; diff --git a/javatests/com/jnibind/test/global_object_test_jni.cc b/javatests/com/jnibind/test/global_object_test_jni.cc index ee27b44..395e1b9 100644 --- a/javatests/com/jnibind/test/global_object_test_jni.cc +++ b/javatests/com/jnibind/test/global_object_test_jni.cc @@ -22,8 +22,12 @@ static std::unique_ptr> jvm; +constexpr jni::Class kBase{ + "kBase", jni::Method{"toString", jni::Return{}, jni::Params{}}}; + constexpr jni::Class kGlobalObjectTestClass{ "com/jnibind/test/GlobalObjectTest", + jni::Extends{kBase}, jni::Method{"methodTakesGlobalObjectReturnsNewObject", jni::Return{kObjectTestHelperClass}, jni::Params{kObjectTestHelperClass}}, @@ -63,9 +67,11 @@ Java_com_jnibind_test_GlobalObjectTest_jniBuildNewObjectsFromExistingObjects( JNIEnv* env, jclass, jobject test_helper_object, jobject object_to_mutate) { jni::LocalObject helper_obj{object_to_mutate}; - return jni::LocalObject{test_helper_object}( - "methodTakesGlobalObjectReturnsNewObject", helper_obj) - .Release(); + auto a = jni::LocalObject{test_helper_object}( + "methodTakesGlobalObjectReturnsNewObject", helper_obj); + // a("toString"); + + return a.Release(); } JNIEXPORT jobject JNICALL diff --git a/jni_bind.h b/jni_bind.h index 6c4c79c..ca6904d 100644 --- a/jni_bind.h +++ b/jni_bind.h @@ -63,6 +63,7 @@ static constexpr Configuration kConfig{ #include "implementation/forward_declarations.h" #include "implementation/id.h" #include "implementation/id_type.h" +#include "implementation/inheritance.h" #include "implementation/jni_type.h" #include "implementation/jvm.h" #include "implementation/loaded_by.h"