Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions apps/example/src/getTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,14 @@ export function getTests(
.didNotThrow()
.equals(55)
),
createTest('getSyncNumberCallback()() returns a number', () =>
it(() => {
const callback = testObject.getSyncNumberCallback()
return callback()
})
.didNotThrow()
.equals(55)
),
createTest('bounceExternalHybrid(...) works', () =>
it(() => {
return testObject.bounceExternalHybrid(HybridSomeExternalObject)
Expand Down
26 changes: 24 additions & 2 deletions packages/nitrogen/src/syntax/kotlin/KotlinFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,25 @@ import { includeHeader } from '../c++/includeNitroHeader.js'
import { createFileMetadataString, isNotDuplicate } from '../helpers.js'
import type { SourceFile } from '../SourceFile.js'
import type { FunctionType } from '../types/FunctionType.js'
import type { Type } from '../types/Type.js'
import { addJNINativeRegistration } from './JNINativeRegistrations.js'
import { KotlinCxxBridgedType } from './KotlinCxxBridgedType.js'

/**
* Whether the JVM signature of the generated `fun interface`'s `invoke` boxes the
* given return type. `Unit` maps to `void`, every other primitive is boxed.
*/
function hasBoxedJvmReturnType(returnType: Type): boolean {
switch (returnType.kind) {
case 'number':
case 'boolean':
case 'int64':
return true
default:
return false
}
}

export function createKotlinFunction(functionType: FunctionType): SourceFile[] {
const name = functionType.specializationName
const packageName = NitroConfig.current.getAndroidPackage('java/kotlin')
Expand Down Expand Up @@ -110,6 +126,9 @@ class ${name}_java(private val function: ${lambdaSignature}): ${name} {
`${name}_cxx`
)
const bridgedReturn = new KotlinCxxBridgedType(functionType.returnType)
// `invoke` overrides `FunctionN.invoke`, whose return type is a generic - so Kotlin
// boxes it. Parameters are unaffected, they are specialized to primitives.
const isReturnBoxed = hasBoxedJvmReturnType(functionType.returnType)
const cxxNamespace = NitroConfig.current.getCxxNamespace('c++')
const typename = functionType.getCode('c++')

Expand Down Expand Up @@ -139,7 +158,10 @@ class ${name}_java(private val function: ${lambdaSignature}): ${name} {
return bridge.parseFromCppToKotlin(p.escapedName, 'c++', false)
}),
]
const jniSignature = `${bridgedReturn.asJniReferenceType('local')}(${functionType.parameters
const jniReturnType = isReturnBoxed
? `jni::local_ref<${bridgedReturn.getTypeCode('c++', true)}>`
: bridgedReturn.asJniReferenceType('local')
const jniSignature = `${jniReturnType}(${functionType.parameters
.map((p) => {
const bridge = new KotlinCxxBridgedType(p)
return `${bridge.asJniReferenceType('alias')} /* ${p.escapedName} */`
Expand All @@ -164,7 +186,7 @@ return ${bridgedReturn.parseFromCppToKotlin('__result', 'c++')};
jniCallBody = `
static const auto method = javaClassStatic()->getMethod<${jniSignature}>("invoke");
auto __result = method(${jniParamsForward.join(', ')});
return ${bridgedReturn.parseFromKotlinToCpp('__result', 'c++', false)};
return ${bridgedReturn.parseFromKotlinToCpp('__result', 'c++', isReturnBoxed)};
`.trim()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,10 @@ class HybridTestObjectKotlin : HybridTestObjectSwiftKotlinSpec() {
return value
}

override fun getSyncNumberCallback(): () -> Double {
return { 55.0 }
}

override fun bounceExternalHybrid(externalObject: HybridSomeExternalObjectSpec): HybridSomeExternalObjectSpec {
return externalObject
}
Expand Down
4 changes: 4 additions & 0 deletions packages/react-native-nitro-test/cpp/HybridTestObjectCpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,10 @@ double HybridTestObjectCpp::callbackSync(const std::function<double()>& callback
return value;
}

std::function<double()> HybridTestObjectCpp::getSyncNumberCallback() {
return []() -> double { return 55; };
}

std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec> HybridTestObjectCpp::bounceExternalHybrid(
const std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec>& externalObject) {
return externalObject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ class HybridTestObjectCpp : public HybridTestObjectCppSpec {

bool getIsViewBlue(const std::shared_ptr<HybridTestViewSpec>& view) override;
double callbackSync(const std::function<double()>& callback) override;
std::function<double()> getSyncNumberCallback() override;

std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec>
bounceExternalHybrid(const std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec>& externalObject) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,10 @@ class HybridTestObjectSwift: HybridTestObjectSwiftKotlinSpec {
return value
}

func getSyncNumberCallback() throws -> () -> Double {
return { 55 }
}

func bounceExternalHybrid(externalObject: (any HybridSomeExternalObjectSpec)) throws -> (
any HybridSomeExternalObjectSpec
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "JHybridTestObjectSwiftKotlinSpec.hpp"
#include "JFunc_void_double.hpp"
#include "JFunc_void.hpp"
#include "JFunc_double.hpp"
#include "JFunc_void_std__vector_Powertrain_.hpp"
#include "JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void____.hpp"
#include "JFunc_void_std__optional_double_.hpp"
Expand All @@ -32,7 +33,6 @@
#include "JFunc_void_std__string.hpp"
#include "JFunc_void_std__exception_ptr.hpp"
#include "JFunc_std__shared_ptr_Promise_std__string__.hpp"
#include "JFunc_double.hpp"
#include "JFunc_std__shared_ptr_margelo__nitro__test__external__HybridSomeExternalObjectSpec_.hpp"
#include "JHybridTestViewSpec.hpp"
#include "views/JHybridTestViewStateUpdater.hpp"
Expand Down Expand Up @@ -109,6 +109,7 @@ void registerAllNatives() {
margelo::nitro::test::JHybridTestObjectSwiftKotlinSpec::CxxPart::registerNatives();
margelo::nitro::test::JFunc_void_double_cxx::registerNatives();
margelo::nitro::test::JFunc_void_cxx::registerNatives();
margelo::nitro::test::JFunc_double_cxx::registerNatives();
margelo::nitro::test::JFunc_void_std__vector_Powertrain__cxx::registerNatives();
margelo::nitro::test::JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____cxx::registerNatives();
margelo::nitro::test::JFunc_void_std__optional_double__cxx::registerNatives();
Expand All @@ -118,7 +119,6 @@ void registerAllNatives() {
margelo::nitro::test::JFunc_void_std__string_cxx::registerNatives();
margelo::nitro::test::JFunc_void_std__exception_ptr_cxx::registerNatives();
margelo::nitro::test::JFunc_std__shared_ptr_Promise_std__string___cxx::registerNatives();
margelo::nitro::test::JFunc_double_cxx::registerNatives();
margelo::nitro::test::JFunc_std__shared_ptr_margelo__nitro__test__external__HybridSomeExternalObjectSpec__cxx::registerNatives();
margelo::nitro::test::JHybridTestViewSpec::CxxPart::registerNatives();
margelo::nitro::test::views::JHybridTestViewStateUpdater::registerNatives();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ namespace margelo::nitro::test {
* Invokes the function this `JFunc_double` instance holds through JNI.
*/
double invoke() const {
static const auto method = javaClassStatic()->getMethod<double()>("invoke");
static const auto method = javaClassStatic()->getMethod<jni::local_ref<jni::JDouble>()>("invoke");
auto __result = method(self());
return __result;
return __result->value();
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ namespace margelo::nitro::test { class HybridTestViewSpec; }
#include "JVariant_HybridBaseSpec_OptionalWrapper.hpp"
#include "JHybridBaseSpec.hpp"
#include "JCoreTypesVariant.hpp"
#include "JFunc_double.hpp"
#include <NitroTestExternal/HybridSomeExternalObjectSpec.hpp>
#include <NitroTestExternal/JHybridSomeExternalObjectSpec.hpp>
#include "ExternalObjectStruct.hpp"
Expand All @@ -135,7 +136,6 @@ namespace margelo::nitro::test { class HybridTestViewSpec; }
#include "HardwareBufferFormat.hpp"
#include "JHardwareBufferFormat.hpp"
#include "JVariant_Boolean_DoubleArray_Array_String__Double_String.hpp"
#include "JFunc_double.hpp"
#include "HybridTestViewSpec.hpp"
#include "JHybridTestViewSpec.hpp"
#include "JFunc_std__shared_ptr_margelo__nitro__test__external__HybridSomeExternalObjectSpec_.hpp"
Expand Down Expand Up @@ -1523,6 +1523,19 @@ namespace margelo::nitro::test {
auto __result = method(_javaPart, JFunc_double_cxx::fromCpp(callback));
return __result;
}
std::function<double()> JHybridTestObjectSwiftKotlinSpec::getSyncNumberCallback() {
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JFunc_double::javaobject>()>("getSyncNumberCallback_cxx");
auto __result = method(_javaPart);
return [&]() -> std::function<double()> {
if (__result->isInstanceOf(JFunc_double_cxx::javaClassStatic())) [[likely]] {
auto downcast = jni::static_ref_cast<JFunc_double_cxx::javaobject>(__result);
return downcast->cthis()->getFunction();
} else {
auto __resultRef = jni::make_global(__result);
return JNICallable<JFunc_double, double()>(std::move(__resultRef));
}
}();
}
bool JHybridTestObjectSwiftKotlinSpec::getIsViewBlue(const std::shared_ptr<HybridTestViewSpec>& view) {
static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean(jni::alias_ref<JHybridTestViewSpec::JavaPart> /* view */)>("getIsViewBlue");
auto __result = method(_javaPart, std::dynamic_pointer_cast<JHybridTestViewSpec>(view)->getJavaPart());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ namespace margelo::nitro::test {
std::shared_ptr<HybridBaseSpec> bounceChildBase(const std::shared_ptr<HybridChildSpec>& child) override;
std::shared_ptr<HybridChildSpec> castBase(const std::shared_ptr<HybridBaseSpec>& base) override;
double callbackSync(const std::function<double()>& callback) override;
std::function<double()> getSyncNumberCallback() override;
bool getIsViewBlue(const std::shared_ptr<HybridTestViewSpec>& view) override;
std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec> bounceExternalHybrid(const std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec>& externalObject) override;
std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec> createInternalObject() override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,15 @@ abstract class HybridTestObjectSwiftKotlinSpec: HybridObject() {
return __result
}

abstract fun getSyncNumberCallback(): () -> Double

@DoNotStrip
@Keep
private fun getSyncNumberCallback_cxx(): Func_double {
val __result = getSyncNumberCallback()
return Func_double_java(__result)
}

@DoNotStrip
@Keep
abstract fun getIsViewBlue(view: HybridTestViewSpec): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2304,6 +2304,15 @@ namespace margelo::nitro::test::bridge::swift {
return Result<std::shared_ptr<HybridBaseSpec>>::withError(error);
}

// pragma MARK: Result<std::function<double()>>
using Result_std__function_double____ = Result<std::function<double()>>;
inline Result_std__function_double____ create_Result_std__function_double____(const std::function<double()>& value) noexcept {
return Result<std::function<double()>>::withValue(value);
}
inline Result_std__function_double____ create_Result_std__function_double____(const std::exception_ptr& error) noexcept {
return Result<std::function<double()>>::withError(error);
}

// pragma MARK: Result<std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec>>
using Result_std__shared_ptr_margelo__nitro__test__external__HybridSomeExternalObjectSpec__ = Result<std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec>>;
inline Result_std__shared_ptr_margelo__nitro__test__external__HybridSomeExternalObjectSpec__ create_Result_std__shared_ptr_margelo__nitro__test__external__HybridSomeExternalObjectSpec__(const std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec>& value) noexcept {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,14 @@ namespace margelo::nitro::test {
auto __value = std::move(__result.value());
return __value;
}
inline std::function<double()> getSyncNumberCallback() override {
auto __result = _swiftPart.getSyncNumberCallback();
if (__result.hasError()) [[unlikely]] {
std::rethrow_exception(__result.error());
}
auto __value = std::move(__result.value());
return __value;
}
inline bool getIsViewBlue(const std::shared_ptr<HybridTestViewSpec>& view) override {
auto __result = _swiftPart.getIsViewBlue(view);
if (__result.hasError()) [[unlikely]] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ public protocol HybridTestObjectSwiftKotlinSpec_protocol: HybridObject {
func bounceChildBase(child: (any HybridChildSpec)) throws -> (any HybridBaseSpec)
func castBase(base: (any HybridBaseSpec)) throws -> (any HybridChildSpec)
func callbackSync(callback: @escaping () -> Double) throws -> Double
func getSyncNumberCallback() throws -> () -> Double
func getIsViewBlue(view: (any HybridTestViewSpec)) throws -> Bool
func bounceExternalHybrid(externalObject: (any HybridSomeExternalObjectSpec)) throws -> (any HybridSomeExternalObjectSpec)
func createInternalObject() throws -> (any HybridSomeExternalObjectSpec)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2871,6 +2871,21 @@ open class HybridTestObjectSwiftKotlinSpec_cxx {
}
}

@inline(__always)
public final func getSyncNumberCallback() -> bridge.Result_std__function_double____ {
do {
let __result = try self.__implementation.getSyncNumberCallback()
let __resultCpp = { () -> bridge.Func_double in
let __closureWrapper = Func_double(__result)
return bridge.create_Func_double(__closureWrapper.toUnsafe())
}()
return bridge.create_Result_std__function_double____(__resultCpp)
} catch (let __error) {
let __exceptionPtr = __error.toCpp()
return bridge.create_Result_std__function_double____(__exceptionPtr)
}
}

@inline(__always)
public final func getIsViewBlue(view: bridge.std__shared_ptr_HybridTestViewSpec_) -> bridge.Result_bool_ {
do {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ namespace margelo::nitro::test {
prototype.registerHybridMethod("bounceChildBase", &HybridTestObjectCppSpec::bounceChildBase);
prototype.registerHybridMethod("castBase", &HybridTestObjectCppSpec::castBase);
prototype.registerHybridMethod("callbackSync", &HybridTestObjectCppSpec::callbackSync);
prototype.registerHybridMethod("getSyncNumberCallback", &HybridTestObjectCppSpec::getSyncNumberCallback);
prototype.registerHybridMethod("getIsViewBlue", &HybridTestObjectCppSpec::getIsViewBlue);
prototype.registerHybridMethod("bounceExternalHybrid", &HybridTestObjectCppSpec::bounceExternalHybrid);
prototype.registerHybridMethod("createInternalObject", &HybridTestObjectCppSpec::createInternalObject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ namespace margelo::nitro::test {
virtual std::shared_ptr<HybridBaseSpec> bounceChildBase(const std::shared_ptr<HybridChildSpec>& child) = 0;
virtual std::shared_ptr<HybridChildSpec> castBase(const std::shared_ptr<HybridBaseSpec>& base) = 0;
virtual double callbackSync(const std::function<double()>& callback) = 0;
virtual std::function<double()> getSyncNumberCallback() = 0;
virtual bool getIsViewBlue(const std::shared_ptr<HybridTestViewSpec>& view) = 0;
virtual std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec> bounceExternalHybrid(const std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec>& externalObject) = 0;
virtual std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec> createInternalObject() = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ namespace margelo::nitro::test {
prototype.registerHybridMethod("bounceChildBase", &HybridTestObjectSwiftKotlinSpec::bounceChildBase);
prototype.registerHybridMethod("castBase", &HybridTestObjectSwiftKotlinSpec::castBase);
prototype.registerHybridMethod("callbackSync", &HybridTestObjectSwiftKotlinSpec::callbackSync);
prototype.registerHybridMethod("getSyncNumberCallback", &HybridTestObjectSwiftKotlinSpec::getSyncNumberCallback);
prototype.registerHybridMethod("getIsViewBlue", &HybridTestObjectSwiftKotlinSpec::getIsViewBlue);
prototype.registerHybridMethod("bounceExternalHybrid", &HybridTestObjectSwiftKotlinSpec::bounceExternalHybrid);
prototype.registerHybridMethod("createInternalObject", &HybridTestObjectSwiftKotlinSpec::createInternalObject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ namespace margelo::nitro::test {
virtual std::shared_ptr<HybridBaseSpec> bounceChildBase(const std::shared_ptr<HybridChildSpec>& child) = 0;
virtual std::shared_ptr<HybridChildSpec> castBase(const std::shared_ptr<HybridBaseSpec>& base) = 0;
virtual double callbackSync(const std::function<double()>& callback) = 0;
virtual std::function<double()> getSyncNumberCallback() = 0;
virtual bool getIsViewBlue(const std::shared_ptr<HybridTestViewSpec>& view) = 0;
virtual std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec> bounceExternalHybrid(const std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec>& externalObject) = 0;
virtual std::shared_ptr<margelo::nitro::test::external::HybridSomeExternalObjectSpec> createInternalObject() = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ interface SharedTestObjectProps {

// Sync funcs
callbackSync(callback: Sync<() => number>): number
getSyncNumberCallback(): Sync<() => number>

// Views
getIsViewBlue(view: TestView): boolean
Expand Down