1 // 2 // Copyright © 2017 Arm Ltd. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 // 5 6 #include <armnn/backends/DynamicBackend.hpp> 7 #include <backendsCommon/DynamicBackendUtils.hpp> 8 9 namespace armnn 10 { 11 DynamicBackend(const void * sharedObjectHandle)12DynamicBackend::DynamicBackend(const void* sharedObjectHandle) 13 : m_BackendIdFunction(nullptr) 14 , m_BackendVersionFunction(nullptr) 15 , m_BackendFactoryFunction(nullptr) 16 , m_Handle(const_cast<void*>(sharedObjectHandle), &DynamicBackendUtils::CloseHandle) 17 { 18 if (m_Handle == nullptr) 19 { 20 throw InvalidArgumentException("Cannot create a DynamicBackend object from an invalid shared object handle"); 21 } 22 23 // These calls will throw in case of error 24 m_BackendIdFunction = SetFunctionPointer<IdFunctionType>("GetBackendId"); 25 m_BackendVersionFunction = SetFunctionPointer<VersionFunctionType>("GetVersion"); 26 m_BackendFactoryFunction = SetFunctionPointer<FactoryFunctionType>("BackendFactory"); 27 28 // Check that the backend is compatible with the current Backend API 29 BackendId backendId = GetBackendId(); 30 BackendVersion backendVersion = GetBackendVersion(); 31 if (!DynamicBackendUtils::IsBackendCompatible(backendVersion)) 32 { 33 // This exception message could not be formatted simply using fmt::format 34 std::stringstream message; 35 message << "The dynamic backend " << backendId << " (version " << backendVersion << 36 ") is not compatible with the current Backend API (version " << IBackendInternal::GetApiVersion() << ")"; 37 38 throw RuntimeException(message.str()); 39 } 40 } 41 GetBackendId()42BackendId DynamicBackend::GetBackendId() 43 { 44 if (m_BackendIdFunction == nullptr) 45 { 46 throw RuntimeException("GetBackendId error: invalid function pointer"); 47 } 48 49 const char* backendId = m_BackendIdFunction(); 50 if (backendId == nullptr) 51 { 52 throw RuntimeException("GetBackendId error: invalid backend id"); 53 } 54 55 return BackendId(backendId); 56 } 57 GetBackendVersion()58BackendVersion DynamicBackend::GetBackendVersion() 59 { 60 if (m_BackendVersionFunction == nullptr) 61 { 62 throw RuntimeException("GetBackendVersion error: invalid function pointer"); 63 } 64 65 uint32_t major = 0; 66 uint32_t minor = 0; 67 m_BackendVersionFunction(&major, &minor); 68 69 return BackendVersion{ major, minor }; 70 } 71 GetBackend()72IBackendInternalUniquePtr DynamicBackend::GetBackend() 73 { 74 // This call throws in case of error 75 return CreateBackend(); 76 } 77 GetFactoryFunction()78BackendRegistry::FactoryFunction DynamicBackend::GetFactoryFunction() 79 { 80 if (m_BackendFactoryFunction == nullptr) 81 { 82 throw RuntimeException("GetFactoryFunction error: invalid function pointer"); 83 } 84 85 return [this]() -> IBackendInternalUniquePtr 86 { 87 // This call throws in case of error 88 return CreateBackend(); 89 }; 90 } 91 92 template<typename BackendFunctionType> SetFunctionPointer(const std::string & backendFunctionName)93BackendFunctionType DynamicBackend::SetFunctionPointer(const std::string& backendFunctionName) 94 { 95 if (m_Handle == nullptr) 96 { 97 throw RuntimeException("SetFunctionPointer error: invalid shared object handle"); 98 } 99 100 if (backendFunctionName.empty()) 101 { 102 throw RuntimeException("SetFunctionPointer error: backend function name must not be empty"); 103 } 104 105 // This call will throw in case of error 106 auto functionPointer = DynamicBackendUtils::GetEntryPoint<BackendFunctionType>(m_Handle.get(), 107 backendFunctionName.c_str()); 108 if (!functionPointer) 109 { 110 throw RuntimeException("SetFunctionPointer error: invalid backend function pointer returned"); 111 } 112 113 return functionPointer; 114 } 115 CreateBackend()116IBackendInternalUniquePtr DynamicBackend::CreateBackend() 117 { 118 if (m_BackendFactoryFunction == nullptr) 119 { 120 throw RuntimeException("CreateBackend error: invalid function pointer"); 121 } 122 123 auto backendPointer = reinterpret_cast<IBackendInternal*>(m_BackendFactoryFunction()); 124 if (backendPointer == nullptr) 125 { 126 throw RuntimeException("CreateBackend error: backend instance must not be null"); 127 } 128 129 return std::unique_ptr<IBackendInternal>(backendPointer); 130 } 131 132 } // namespace armnn 133