Holoscan SDK v4.1.0

Program Listing for File component-inl.hpp

Return to documentation for file (include/holoscan/core/component-inl.hpp)

Copy
Copied!
            

/* * SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * * 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 HOLOSCAN_CORE_COMPONENT_INL_HPP #define HOLOSCAN_CORE_COMPONENT_INL_HPP #include <memory> // For std::shared_ptr, std::static_pointer_cast #include <string> #include <string_view> #include <typeinfo> // For typeid #include <utility> // NOLINTNEXTLINE(misc-header-include-cycle) circular dependency with condition.hpp is intentional #include "./argument_setter.hpp" #include "./fragment_service.hpp" #include "./fragment_service_provider.hpp" namespace holoscan { template <typename typeT> void ComponentBase::register_argument_setter() { ArgumentSetter::get_instance().add_argument_setter<typeT>( [](ParameterWrapper& param_wrap, Arg& arg) -> bool { std::any& any_param = param_wrap.value(); // If arg has no name and value, that indicates that we want to set the default value for // the native operator if it is not specified. if (arg.name().empty() && !arg.has_value()) { auto& param = *std::any_cast<Parameter<typeT>*>(any_param); param.set_default_value(); return true; } std::any& any_arg = arg.value(); // Note that the type of any_param is Parameter<typeT>*, not Parameter<typeT>. auto& param = *std::any_cast<Parameter<typeT>*>(any_param); const auto& arg_type = arg.arg_type(); auto element_type = arg_type.element_type(); auto container_type = arg_type.container_type(); HOLOSCAN_LOG_DEBUG( "Registering converter for parameter {} (element_type: {}, container_type: {})", arg.name(), static_cast<int>(element_type), static_cast<int>(container_type)); if (element_type == ArgElementType::kYAMLNode) { auto& arg_value = std::any_cast<YAML::Node&>(any_arg); typeT new_value; bool parse_ok = YAML::convert<typeT>::decode(arg_value, new_value); if (!parse_ok) { HOLOSCAN_LOG_ERROR("Unable to parse YAML node for parameter '{}'", arg.name()); return false; } else { param = std::move(new_value); return true; } } else { try { auto& arg_value = std::any_cast<typeT&>(any_arg); param = arg_value; return true; } catch (const std::bad_any_cast& e) { // Capture type information for detailed error reporting const char* expected = typeid(typeT).name(); const std::type_info& actual_type = any_arg.type(); const char* actual = actual_type == typeid(void) ? "<empty>" : actual_type.name(); std::string error_message = fmt::format("Bad any cast while setting argument '{}': expected '{}', got '{}'. {}", arg.name(), expected, actual, e.what()); HOLOSCAN_LOG_ERROR(error_message); return false; } } }); } template <typename ServiceT> std::shared_ptr<ServiceT> ComponentBase::service(std::string_view id) const { static_assert(holoscan::is_one_of_derived_v<ServiceT, Resource, FragmentService>, "ServiceT must inherit from Resource or FragmentService"); // Early return if no service provider is available if (!service_provider_) { HOLOSCAN_LOG_DEBUG("Component '{}': No service provider available.", name()); return nullptr; } // Get the base service from the provider auto base_service = service_provider_->get_service_erased(typeid(ServiceT), id); if (!base_service) { // Keep this fallback lookup logic in sync with Fragment::service(). // Fallback: try to find a service by id only (ignoring type key) and check if it's // type-castable to ServiceT. This enables retrieval of services registered with a derived // type when looking up by a base type. if constexpr (std::is_base_of_v<Resource, ServiceT>) { if (!id.empty()) { auto service_resource_by_name = service_provider_->get_service_resource_by_name(id); if (service_resource_by_name) { auto typed_resource = std::dynamic_pointer_cast<ServiceT>(service_resource_by_name); if (typed_resource) { return typed_resource; } HOLOSCAN_LOG_DEBUG( "Component '{}': Service resource with id '{}' is not type-castable to type '{}'.", name(), std::string(id), typeid(ServiceT).name()); } } } else if constexpr (std::is_base_of_v<FragmentService, ServiceT>) { // For FragmentService-derived types (non-Resource), search by id and try dynamic_cast if (!id.empty()) { auto services_by_id = service_provider_->get_services_by_id(id); for (const auto& svc : services_by_id) { auto typed_service = std::dynamic_pointer_cast<ServiceT>(svc); if (typed_service) { HOLOSCAN_LOG_DEBUG( "Component '{}': Service with id '{}' found via base-class fallback lookup.", name(), std::string(id)); return typed_service; } } } } HOLOSCAN_LOG_DEBUG("Component '{}': Service of type {} with id '{}' not found.", name(), typeid(ServiceT).name(), std::string(id)); return nullptr; } // Handle Resource-derived services if constexpr (std::is_base_of_v<Resource, ServiceT>) { auto resource_ptr = base_service->resource(); if (!resource_ptr) { HOLOSCAN_LOG_DEBUG( "Component '{}': No service resource is available for service with id '{}'.", name(), std::string(id)); return nullptr; } // Attempt to cast the resource to the requested type auto typed_resource = std::dynamic_pointer_cast<ServiceT>(resource_ptr); if (!typed_resource) { HOLOSCAN_LOG_DEBUG( "Component '{}': Service resource with id '{}' is not type-castable to type '{}'.", name(), std::string(id), typeid(ServiceT).name()); } return typed_resource; } else { // Handle FragmentService-derived services // Since DefaultFragmentService implements FragmentService, we can safely cast auto typed_service = std::dynamic_pointer_cast<ServiceT>(base_service); if (!typed_service) { HOLOSCAN_LOG_DEBUG("Component '{}': Service with id '{}' is not type-castable to type '{}'.", name(), std::string(id), typeid(ServiceT).name()); } return typed_service; } } inline std::shared_ptr<FragmentService> ComponentBase::get_service_by_type_info( const std::type_info& service_type, std::string_view id) const { if (!service_provider_) { HOLOSCAN_LOG_DEBUG("Component '{}': No service provider available.", name()); return nullptr; } return service_provider_->get_service_erased(service_type, id); } } // namespace holoscan #endif/* HOLOSCAN_CORE_COMPONENT_INL_HPP */

© Copyright 2022-2026, NVIDIA. Last updated on May 11, 2026