/* * Copyright (c) 2024 Huawei Device Co., Ltd. * 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 OHOS_FFI_CJ_LAMBDA_H #define OHOS_FFI_CJ_LAMBDA_H #include #include #include "ffi_remote_data.h" #ifndef FFI_EXPORT #ifndef WINDOWS_PLATFORM #define FFI_EXPORT __attribute__((visibility("default"))) #else #define FFI_EXPORT __declspec(dllexport) #endif #endif class FFI_EXPORT CJLambda { template struct TupleRuntimeHelper { template static void* GetElementAddr(T& tup, size_t idx) { if (idx == I - 1) { return &(std::get(tup)); } else { return TupleRuntimeHelper::GetElementAddr(tup, idx); } } }; template <> struct TupleRuntimeHelper<0> { template static void* GetElementAddr(T& tup, size_t idx) { // Unreachable return nullptr; } }; template static inline void* GetElementAddr(std::tuple const& tup, size_t idx) { return TupleRuntimeHelper::GetElementAddr(tup, idx); } template static inline void* GetElementAddr(std::tuple& tup, size_t idx) { return TupleRuntimeHelper::GetElementAddr(tup, idx); } public: template static std::function Create(void (*callback)(I...)) { auto handle = OHOS::FFI::RemoteData::Create(reinterpret_cast(callback)); return [handle](I...args) -> void { constexpr int32_t argc = std::tuple_size_v>; if (argc == 0) { InvokeLambda(handle->GetID(), argc, nullptr, nullptr); return; } auto argsTuple = std::make_tuple(args...); void* argv[argc]; for (size_t i = 0; i < argc; ++i) { argv[i] = GetElementAddr(argsTuple, i); } InvokeLambda(handle->GetID(), argc, argv, nullptr); }; } template static std::function Create(R (*callback)(I...)) { auto handle = OHOS::FFI::RemoteData::Create(reinterpret_cast(callback)); return [handle](I...args) -> R { R res; constexpr int32_t argc = std::tuple_size_v>; if (argc == 0) { InvokeLambda(handle->GetID(), argc, nullptr, &res); return res; } auto argsTuple = std::make_tuple(args...); void* argv[argc]; for (size_t i = 0; i < argc; ++i) { argv[i] = GetElementAddr(argsTuple, i); } InvokeLambda(handle->GetID(), argc, argv, &res); return res; }; } private: static inline void InvokeLambda(int64_t lambdaId, int32_t argc, void** argv, void* result) { auto invoker = CJFFIFnInvoker::GetInstance()->GetCJFuncs().atCOHOSFFICallbackInvoker; invoker(lambdaId, argc, argv, result); } }; #endif // OHOS_FFI_CJ_LAMBDA_H