! * \brief ffi::Function is a type-erased function. * The arguments are passed by "packed format" via AnyView */
| 318 | * The arguments are passed by "packed format" via AnyView |
| 319 | */ |
| 320 | class Function : public ObjectRef { |
| 321 | public: |
| 322 | /*! \brief Constructor from null */ |
| 323 | Function(std::nullptr_t) : ObjectRef(nullptr) {} // NOLINT(*) |
| 324 | /*! |
| 325 | * \brief Constructing a packed function from a callable type |
| 326 | * whose signature is consistent with `ffi::Function` |
| 327 | * \param packed_call The packed function signature |
| 328 | * \note legacy purpose, should change to Function::FromPacked for mostfuture use. |
| 329 | */ |
| 330 | template <typename TCallable, |
| 331 | typename = std::enable_if_t<!std::is_same_v<std::decay_t<TCallable>, Function>>> |
| 332 | explicit Function(TCallable&& packed_call) { |
| 333 | *this = FromPacked(std::forward<TCallable>(packed_call)); |
| 334 | } |
| 335 | /*! |
| 336 | * \brief Constructing a packed function from a callable type |
| 337 | * whose signature is consistent with `ffi::Function` |
| 338 | * \param packed_call The packed function signature |
| 339 | */ |
| 340 | template <typename TCallable> |
| 341 | static Function FromPacked(TCallable&& packed_call) { |
| 342 | static_assert( |
| 343 | std::is_convertible_v<TCallable, std::function<void(const AnyView*, int32_t, Any*)>> || |
| 344 | std::is_convertible_v<TCallable, std::function<void(PackedArgs args, Any*)>>, |
| 345 | "tvm::ffi::Function::FromPacked requires input function signature to match packed func " |
| 346 | "format"); |
| 347 | if constexpr (std::is_convertible_v<TCallable, std::function<void(PackedArgs args, Any*)>>) { |
| 348 | return FromPackedInternal( |
| 349 | [packed_call = std::forward<TCallable>(packed_call)]( |
| 350 | const AnyView* args, int32_t num_args, Any* rv) mutable -> void { |
| 351 | packed_call(PackedArgs{args, num_args}, rv); |
| 352 | }); |
| 353 | } else { |
| 354 | return FromPackedInternal(std::forward<TCallable>(packed_call)); |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | /*! |
| 359 | * \brief Constructing a packed function from a callable type |
| 360 | * whose signature is consistent with `ffi::Function`. |
| 361 | * It will create the Callable object with the given arguments, |
| 362 | * and return the inplace constructed Function along with |
| 363 | * the pointer to the callable object. The lifetime of the callable |
| 364 | * object is managed by the returned Function. |
| 365 | * \param args The arguments to construct TCallable |
| 366 | * \return A tuple of (Function, TCallable*) |
| 367 | */ |
| 368 | template <typename TCallable, typename... Args> |
| 369 | static auto FromPackedInplace(Args&&... args) { |
| 370 | // We must ensure TCallable is a value type (decay_t) that can hold the callable object |
| 371 | static_assert(std::is_same_v<TCallable, std::decay_t<TCallable>>); |
| 372 | static_assert(std::is_invocable_v<TCallable, const AnyView*, int32_t, Any*>); |
| 373 | using ObjType = details::FunctionObjImpl<TCallable>; |
| 374 | Function func; |
| 375 | auto obj_ptr = make_object<ObjType>(std::forward<Args>(args)...); |
| 376 | auto* call_ptr = obj_ptr->GetCallable(); |
| 377 | func.data_ = std::move(obj_ptr); |