133eb0b6dSopenharmony_ci/* 233eb0b6dSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 333eb0b6dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 433eb0b6dSopenharmony_ci * you may not use this file except in compliance with the License. 533eb0b6dSopenharmony_ci * You may obtain a copy of the License at 633eb0b6dSopenharmony_ci * 733eb0b6dSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 833eb0b6dSopenharmony_ci * 933eb0b6dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1033eb0b6dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1133eb0b6dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1233eb0b6dSopenharmony_ci * See the License for the specific language governing permissions and 1333eb0b6dSopenharmony_ci * limitations under the License. 1433eb0b6dSopenharmony_ci */ 1533eb0b6dSopenharmony_ci 1633eb0b6dSopenharmony_ci#ifndef OHOS_FFI_CJ_LAMBDA_H 1733eb0b6dSopenharmony_ci#define OHOS_FFI_CJ_LAMBDA_H 1833eb0b6dSopenharmony_ci 1933eb0b6dSopenharmony_ci#include <cstdint> 2033eb0b6dSopenharmony_ci#include <tuple> 2133eb0b6dSopenharmony_ci 2233eb0b6dSopenharmony_ci#include "ffi_remote_data.h" 2333eb0b6dSopenharmony_ci 2433eb0b6dSopenharmony_ci#ifndef FFI_EXPORT 2533eb0b6dSopenharmony_ci#ifndef WINDOWS_PLATFORM 2633eb0b6dSopenharmony_ci#define FFI_EXPORT __attribute__((visibility("default"))) 2733eb0b6dSopenharmony_ci#else 2833eb0b6dSopenharmony_ci#define FFI_EXPORT __declspec(dllexport) 2933eb0b6dSopenharmony_ci#endif 3033eb0b6dSopenharmony_ci#endif 3133eb0b6dSopenharmony_ci 3233eb0b6dSopenharmony_ciclass FFI_EXPORT CJLambda { 3333eb0b6dSopenharmony_ci template <size_t I> 3433eb0b6dSopenharmony_ci struct TupleRuntimeHelper { 3533eb0b6dSopenharmony_ci template <typename T> 3633eb0b6dSopenharmony_ci static void* GetElementAddr(T& tup, size_t idx) 3733eb0b6dSopenharmony_ci { 3833eb0b6dSopenharmony_ci if (idx == I - 1) { 3933eb0b6dSopenharmony_ci return &(std::get<I - 1>(tup)); 4033eb0b6dSopenharmony_ci } else { 4133eb0b6dSopenharmony_ci return TupleRuntimeHelper<I - 1>::GetElementAddr(tup, idx); 4233eb0b6dSopenharmony_ci } 4333eb0b6dSopenharmony_ci } 4433eb0b6dSopenharmony_ci }; 4533eb0b6dSopenharmony_ci 4633eb0b6dSopenharmony_ci template <> 4733eb0b6dSopenharmony_ci struct TupleRuntimeHelper<0> { 4833eb0b6dSopenharmony_ci template <typename T> 4933eb0b6dSopenharmony_ci static void* GetElementAddr(T& tup, size_t idx) 5033eb0b6dSopenharmony_ci { 5133eb0b6dSopenharmony_ci // Unreachable 5233eb0b6dSopenharmony_ci return nullptr; 5333eb0b6dSopenharmony_ci } 5433eb0b6dSopenharmony_ci }; 5533eb0b6dSopenharmony_ci 5633eb0b6dSopenharmony_ci template <typename... Types> 5733eb0b6dSopenharmony_ci static inline void* GetElementAddr(std::tuple<Types...> const& tup, size_t idx) 5833eb0b6dSopenharmony_ci { 5933eb0b6dSopenharmony_ci return TupleRuntimeHelper<sizeof...(Types)>::GetElementAddr(tup, idx); 6033eb0b6dSopenharmony_ci } 6133eb0b6dSopenharmony_ci 6233eb0b6dSopenharmony_ci template <typename... Types> 6333eb0b6dSopenharmony_ci static inline void* GetElementAddr(std::tuple<Types...>& tup, size_t idx) 6433eb0b6dSopenharmony_ci { 6533eb0b6dSopenharmony_ci return TupleRuntimeHelper<sizeof...(Types)>::GetElementAddr(tup, idx); 6633eb0b6dSopenharmony_ci } 6733eb0b6dSopenharmony_cipublic: 6833eb0b6dSopenharmony_ci template<class... I> 6933eb0b6dSopenharmony_ci static std::function<void(I...)> Create(void (*callback)(I...)) 7033eb0b6dSopenharmony_ci { 7133eb0b6dSopenharmony_ci auto handle = OHOS::FFI::RemoteData::Create<OHOS::FFI::CJLambdaRemoteData>(reinterpret_cast<int64_t>(callback)); 7233eb0b6dSopenharmony_ci return [handle](I...args) -> void { 7333eb0b6dSopenharmony_ci constexpr int32_t argc = std::tuple_size_v<std::tuple<I...>>; 7433eb0b6dSopenharmony_ci if (argc == 0) { 7533eb0b6dSopenharmony_ci InvokeLambda(handle->GetID(), argc, nullptr, nullptr); 7633eb0b6dSopenharmony_ci return; 7733eb0b6dSopenharmony_ci } 7833eb0b6dSopenharmony_ci auto argsTuple = std::make_tuple(args...); 7933eb0b6dSopenharmony_ci void* argv[argc]; 8033eb0b6dSopenharmony_ci for (size_t i = 0; i < argc; ++i) { 8133eb0b6dSopenharmony_ci argv[i] = GetElementAddr(argsTuple, i); 8233eb0b6dSopenharmony_ci } 8333eb0b6dSopenharmony_ci InvokeLambda(handle->GetID(), argc, argv, nullptr); 8433eb0b6dSopenharmony_ci }; 8533eb0b6dSopenharmony_ci } 8633eb0b6dSopenharmony_ci 8733eb0b6dSopenharmony_ci template<class... I, class R> 8833eb0b6dSopenharmony_ci static std::function<R(I...)> Create(R (*callback)(I...)) 8933eb0b6dSopenharmony_ci { 9033eb0b6dSopenharmony_ci auto handle = OHOS::FFI::RemoteData::Create<OHOS::FFI::CJLambdaRemoteData>(reinterpret_cast<int64_t>(callback)); 9133eb0b6dSopenharmony_ci return [handle](I...args) -> R { 9233eb0b6dSopenharmony_ci R res; 9333eb0b6dSopenharmony_ci constexpr int32_t argc = std::tuple_size_v<std::tuple<I...>>; 9433eb0b6dSopenharmony_ci if (argc == 0) { 9533eb0b6dSopenharmony_ci InvokeLambda(handle->GetID(), argc, nullptr, &res); 9633eb0b6dSopenharmony_ci return res; 9733eb0b6dSopenharmony_ci } 9833eb0b6dSopenharmony_ci auto argsTuple = std::make_tuple(args...); 9933eb0b6dSopenharmony_ci void* argv[argc]; 10033eb0b6dSopenharmony_ci for (size_t i = 0; i < argc; ++i) { 10133eb0b6dSopenharmony_ci argv[i] = GetElementAddr(argsTuple, i); 10233eb0b6dSopenharmony_ci } 10333eb0b6dSopenharmony_ci InvokeLambda(handle->GetID(), argc, argv, &res); 10433eb0b6dSopenharmony_ci return res; 10533eb0b6dSopenharmony_ci }; 10633eb0b6dSopenharmony_ci } 10733eb0b6dSopenharmony_ci 10833eb0b6dSopenharmony_ciprivate: 10933eb0b6dSopenharmony_ci static inline void InvokeLambda(int64_t lambdaId, int32_t argc, void** argv, void* result) 11033eb0b6dSopenharmony_ci { 11133eb0b6dSopenharmony_ci auto invoker = CJFFIFnInvoker::GetInstance()->GetCJFuncs().atCOHOSFFICallbackInvoker; 11233eb0b6dSopenharmony_ci invoker(lambdaId, argc, argv, result); 11333eb0b6dSopenharmony_ci } 11433eb0b6dSopenharmony_ci}; 11533eb0b6dSopenharmony_ci 11633eb0b6dSopenharmony_ci#endif // OHOS_FFI_CJ_LAMBDA_H 117