diff --git a/dpctl-capi/helper/include/dpctl_string_utils.hpp b/dpctl-capi/helper/include/dpctl_string_utils.hpp new file mode 100644 index 0000000000..3b1d0ae73c --- /dev/null +++ b/dpctl-capi/helper/include/dpctl_string_utils.hpp @@ -0,0 +1,61 @@ +//===--- dpctl_string_utils.hpp - C++ to C string converted -*-C++-*- ===// +// +// Data Parallel Control (dpctl) +// +// Copyright 2020-2021 Intel Corporation +// +// 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. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Helper function to convert a C++ string to a C string. +//===----------------------------------------------------------------------===// +#include +#include +#include + +#pragma once + +namespace dpctl +{ +namespace helper +{ +/*! + * @brief Convert a C++ std::string to a const char* and return the string to + * caller. + * + * @param str A C++ string that has to be converted to a C string. + * @return A const char* string representation of the C++ string. + */ +static inline __dpctl_give const char * +cstring_from_string(const std::string &str) +{ + char *cstr = nullptr; + try { + auto cstr_len = str.length() + 1; + cstr = new char[cstr_len]; +#ifdef _WIN32 + strncpy_s(cstr, cstr_len, str.c_str(), cstr_len); +#else + std::strncpy(cstr, str.c_str(), cstr_len); +#endif + } catch (std::bad_alloc const &ba) { + // \todo log error + std::cerr << ba.what() << '\n'; + } + + return cstr; +} +} // namespace helper +} // namespace dpctl diff --git a/dpctl-capi/include/dpctl_sycl_device_manager.h b/dpctl-capi/include/dpctl_sycl_device_manager.h index 6b81035dd9..dcb1ef3c98 100644 --- a/dpctl-capi/include/dpctl_sycl_device_manager.h +++ b/dpctl-capi/include/dpctl_sycl_device_manager.h @@ -76,6 +76,22 @@ DPCTL_API __dpctl_give DPCTLDeviceVectorRef DPCTLDeviceMgr_GetDevices(int device_identifier); +/*! + * @brief Returns a set of device info attributes as a string. + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return A formatted C string capturing the following attributes: + * - device name + * - driver version + * - vendor + * - profiler support + * - oneapi filter string + * @ingroup DeviceManager + */ +DPCTL_API +__dpctl_give const char * +DPCTLDeviceMgr_GetDeviceInfoStr(__dpctl_keep const DPCTLSyclDeviceRef DRef); + /*! * @brief Returns an index on the given device in the vector returned by * #DPCTLDeviceMgr_GetDevices if found, -1 otherwise. @@ -91,6 +107,7 @@ DPCTLDeviceMgr_GetDevices(int device_identifier); * @return If found, returns the position of the given device in the * vector that would be returned by #DPCTLDeviceMgr_GetDevices if called * with the same device_identifier argument. + * @ingroup DeviceManager */ DPCTL_API int DPCTLDeviceMgr_GetPositionInDevices(__dpctl_keep DPCTLSyclDeviceRef DRef, @@ -122,6 +139,7 @@ DPCTLDeviceMgr_GetCachedContext(__dpctl_keep const DPCTLSyclDeviceRef DRef); * the enum values or a bitwise OR-ed combination. * @return The number of available devices satisfying the condition specified * by the device_identifier bit flag. + * @ingroup DeviceManager */ DPCTL_API size_t DPCTLDeviceMgr_GetNumDevices(int device_identifier); @@ -131,6 +149,7 @@ size_t DPCTLDeviceMgr_GetNumDevices(int device_identifier); * currently supported by dpctl. * * @param DRef A #DPCTLSyclDeviceRef opaque pointer. + * @ingroup DeviceManager */ DPCTL_API void DPCTLDeviceMgr_PrintDeviceInfo(__dpctl_keep const DPCTLSyclDeviceRef DRef); diff --git a/dpctl-capi/source/dpctl_service.cpp b/dpctl-capi/source/dpctl_service.cpp index a9b6816f8c..3457980721 100644 --- a/dpctl-capi/source/dpctl_service.cpp +++ b/dpctl-capi/source/dpctl_service.cpp @@ -26,6 +26,7 @@ #include "dpctl_service.h" #include "Config/dpctl_config.h" +#include "../helper/include/dpctl_string_utils.hpp" #include #include #include @@ -33,18 +34,5 @@ __dpctl_give const char *DPCTLService_GetDPCPPVersion(void) { std::string version = DPCTL_DPCPP_VERSION; - char *version_cstr = nullptr; - try { - auto cstr_len = version.length() + 1; - version_cstr = new char[cstr_len]; -#ifdef _WIN32 - strncpy_s(version_cstr, cstr_len, version.c_str(), cstr_len); -#else - std::strncpy(version_cstr, version.c_str(), cstr_len); -#endif - } catch (std::bad_alloc const &ba) { - // \todo log error - std::cerr << ba.what() << '\n'; - } - return version_cstr; + return dpctl::helper::cstring_from_string(version); } diff --git a/dpctl-capi/source/dpctl_sycl_device_interface.cpp b/dpctl-capi/source/dpctl_sycl_device_interface.cpp index 8ef71b65c4..092d5ea273 100644 --- a/dpctl-capi/source/dpctl_sycl_device_interface.cpp +++ b/dpctl-capi/source/dpctl_sycl_device_interface.cpp @@ -25,6 +25,7 @@ //===----------------------------------------------------------------------===// #include "dpctl_sycl_device_interface.h" +#include "../helper/include/dpctl_string_utils.hpp" #include "../helper/include/dpctl_utils_helper.h" #include "Support/CBindingWrapping.h" #include "dpctl_sycl_device_manager.h" @@ -307,21 +308,12 @@ DPCTLDevice_GetPlatform(__dpctl_keep const DPCTLSyclDeviceRef DRef) __dpctl_give const char * DPCTLDevice_GetName(__dpctl_keep const DPCTLSyclDeviceRef DRef) { - char *cstr_name = nullptr; + const char *cstr_name = nullptr; auto D = unwrap(DRef); if (D) { try { auto name = D->get_info(); - auto cstr_len = name.length() + 1; - cstr_name = new char[cstr_len]; -#ifdef _WIN32 - strncpy_s(cstr_name, cstr_len, name.c_str(), cstr_len); -#else - std::strncpy(cstr_name, name.c_str(), cstr_len); -#endif - } catch (std::bad_alloc const &ba) { - // \todo log error - std::cerr << ba.what() << '\n'; + cstr_name = dpctl::helper::cstring_from_string(name); } catch (runtime_error const &re) { // \todo log error std::cerr << re.what() << '\n'; @@ -333,21 +325,12 @@ DPCTLDevice_GetName(__dpctl_keep const DPCTLSyclDeviceRef DRef) __dpctl_give const char * DPCTLDevice_GetVendor(__dpctl_keep const DPCTLSyclDeviceRef DRef) { - char *cstr_vendor = nullptr; + const char *cstr_vendor = nullptr; auto D = unwrap(DRef); if (D) { try { auto vendor = D->get_info(); - auto cstr_len = vendor.length() + 1; - cstr_vendor = new char[cstr_len]; -#ifdef _WIN32 - strncpy_s(cstr_vendor, cstr_len, vendor.c_str(), cstr_len); -#else - std::strncpy(cstr_vendor, vendor.c_str(), cstr_len); -#endif - } catch (std::bad_alloc const &ba) { - // \todo log error - std::cerr << ba.what() << '\n'; + cstr_vendor = dpctl::helper::cstring_from_string(vendor); } catch (runtime_error const &re) { // \todo log error std::cerr << re.what() << '\n'; @@ -359,21 +342,12 @@ DPCTLDevice_GetVendor(__dpctl_keep const DPCTLSyclDeviceRef DRef) __dpctl_give const char * DPCTLDevice_GetDriverVersion(__dpctl_keep const DPCTLSyclDeviceRef DRef) { - char *cstr_driver = nullptr; + const char *cstr_driver = nullptr; auto D = unwrap(DRef); if (D) { try { auto driver = D->get_info(); - auto cstr_len = driver.length() + 1; - cstr_driver = new char[cstr_len]; -#ifdef _WIN32 - strncpy_s(cstr_driver, cstr_len, driver.c_str(), cstr_len); -#else - std::strncpy(cstr_driver, driver.c_str(), cstr_len); -#endif - } catch (std::bad_alloc const &ba) { - // \todo log error - std::cerr << ba.what() << '\n'; + cstr_driver = dpctl::helper::cstring_from_string(driver); } catch (runtime_error const &re) { // \todo log error std::cerr << re.what() << '\n'; diff --git a/dpctl-capi/source/dpctl_sycl_device_manager.cpp b/dpctl-capi/source/dpctl_sycl_device_manager.cpp index 392056dd09..06bf3cf16a 100644 --- a/dpctl-capi/source/dpctl_sycl_device_manager.cpp +++ b/dpctl-capi/source/dpctl_sycl_device_manager.cpp @@ -24,6 +24,7 @@ //===----------------------------------------------------------------------===// #include "dpctl_sycl_device_manager.h" +#include "../helper/include/dpctl_string_utils.hpp" #include "../helper/include/dpctl_utils_helper.h" #include "Support/CBindingWrapping.h" #include "dpctl_sycl_enum_types.h" @@ -44,7 +45,7 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(context, DPCTLSyclContextRef) /* * Helper function to print the metadata for a sycl::device. */ -void print_device_info(const device &Device) +std::string get_device_info_str(const device &Device) { std::stringstream ss; @@ -61,7 +62,7 @@ void print_device_info(const device &Device) << DPCTL_DeviceTypeToStr(Device.get_info()) << ":" << DPCTL_GetRelativeDeviceId(Device) << '\n'; - std::cout << ss.str(); + return ss.str(); } struct DeviceCacheBuilder @@ -168,6 +169,23 @@ DPCTLDeviceMgr_GetDevices(int device_identifier) return wrap(Devices); } +__dpctl_give const char * +DPCTLDeviceMgr_GetDeviceInfoStr(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + const char *cstr_info = nullptr; + auto D = unwrap(DRef); + if (D) { + try { + auto infostr = get_device_info_str(*D); + cstr_info = dpctl::helper::cstring_from_string(infostr); + } catch (runtime_error const &re) { + // \todo log error + std::cerr << re.what() << '\n'; + } + } + return cstr_info; +} + int DPCTLDeviceMgr_GetPositionInDevices(__dpctl_keep DPCTLSyclDeviceRef DRef, int device_identifier) { @@ -226,7 +244,7 @@ void DPCTLDeviceMgr_PrintDeviceInfo(__dpctl_keep const DPCTLSyclDeviceRef DRef) { auto Device = unwrap(DRef); if (Device) - print_device_info(*Device); + std::cout << get_device_info_str(*Device); else std::cout << "Device is not valid (NULL). Cannot print device info.\n"; } diff --git a/dpctl-capi/source/dpctl_sycl_kernel_interface.cpp b/dpctl-capi/source/dpctl_sycl_kernel_interface.cpp index 2663659d55..b25d73ada0 100644 --- a/dpctl-capi/source/dpctl_sycl_kernel_interface.cpp +++ b/dpctl-capi/source/dpctl_sycl_kernel_interface.cpp @@ -25,6 +25,7 @@ //===----------------------------------------------------------------------===// #include "dpctl_sycl_kernel_interface.h" +#include "../helper/include/dpctl_string_utils.hpp" #include "Support/CBindingWrapping.h" #include /* Sycl headers */ @@ -49,14 +50,7 @@ DPCTLKernel_GetFunctionName(__dpctl_keep const DPCTLSyclKernelRef Kernel) auto kernel_name = SyclKernel->get_info(); if (kernel_name.empty()) return nullptr; - auto cstr_len = kernel_name.length() + 1; - auto cstr_name = new char[cstr_len]; -#ifdef _WIN32 - strncpy_s(cstr_name, cstr_len, kernel_name.c_str(), cstr_len); -#else - std::strncpy(cstr_name, kernel_name.c_str(), cstr_len); -#endif - return cstr_name; + return dpctl::helper::cstring_from_string(kernel_name); } size_t DPCTLKernel_GetNumArgs(__dpctl_keep const DPCTLSyclKernelRef Kernel) diff --git a/dpctl-capi/source/dpctl_sycl_platform_interface.cpp b/dpctl-capi/source/dpctl_sycl_platform_interface.cpp index 56e3fd4a50..3eb3592f79 100644 --- a/dpctl-capi/source/dpctl_sycl_platform_interface.cpp +++ b/dpctl-capi/source/dpctl_sycl_platform_interface.cpp @@ -25,6 +25,7 @@ //===----------------------------------------------------------------------===// #include "dpctl_sycl_platform_interface.h" +#include "../helper/include/dpctl_string_utils.hpp" #include "../helper/include/dpctl_utils_helper.h" #include "Support/CBindingWrapping.h" #include @@ -121,88 +122,61 @@ DPCTLPlatform_GetBackend(__dpctl_keep const DPCTLSyclPlatformRef PRef) __dpctl_give const char * DPCTLPlatform_GetName(__dpctl_keep const DPCTLSyclPlatformRef PRef) { - char *cstr_name = nullptr; auto P = unwrap(PRef); if (P) { try { auto name = P->get_info(); - auto cstr_len = name.length() + 1; - cstr_name = new char[cstr_len]; -#ifdef _WIN32 - strncpy_s(cstr_name, cstr_len, name.c_str(), cstr_len); -#else - std::strncpy(cstr_name, name.c_str(), cstr_len); -#endif - } catch (std::bad_alloc const &ba) { - // \todo log error - std::cerr << ba.what() << '\n'; + return dpctl::helper::cstring_from_string(name); } catch (runtime_error const &re) { // \todo log error std::cerr << re.what() << '\n'; + return nullptr; } } else { std::cerr << "Name cannot be looked up for a NULL platform\n"; + return nullptr; } - return cstr_name; } __dpctl_give const char * DPCTLPlatform_GetVendor(__dpctl_keep const DPCTLSyclPlatformRef PRef) { - char *cstr_vendor = nullptr; auto P = unwrap(PRef); if (P) { try { auto vendor = P->get_info(); - auto cstr_len = vendor.length() + 1; - cstr_vendor = new char[cstr_len]; -#ifdef _WIN32 - strncpy_s(cstr_vendor, cstr_len, vendor.c_str(), cstr_len); -#else - std::strncpy(cstr_vendor, vendor.c_str(), cstr_len); -#endif - } catch (std::bad_alloc const &ba) { - // \todo log error - std::cerr << ba.what() << '\n'; + return dpctl::helper::cstring_from_string(vendor); } catch (runtime_error const &re) { // \todo log error std::cerr << re.what() << '\n'; + return nullptr; } } else { std::cerr << "Vendor cannot be looked up for a NULL platform\n"; + return nullptr; } - return cstr_vendor; } __dpctl_give const char * DPCTLPlatform_GetVersion(__dpctl_keep const DPCTLSyclPlatformRef PRef) { - char *cstr_driver = nullptr; auto P = unwrap(PRef); if (P) { try { auto driver = P->get_info(); - auto cstr_len = driver.length() + 1; - cstr_driver = new char[cstr_len]; -#ifdef _WIN32 - strncpy_s(cstr_driver, cstr_len, driver.c_str(), cstr_len); -#else - std::strncpy(cstr_driver, driver.c_str(), cstr_len); -#endif - } catch (std::bad_alloc const &ba) { - // \todo log error - std::cerr << ba.what() << '\n'; + return dpctl::helper::cstring_from_string(driver); } catch (runtime_error const &re) { // \todo log error std::cerr << re.what() << '\n'; + return nullptr; } } else { std::cerr << "Driver version cannot be looked up for a NULL platform\n"; + return nullptr; } - return cstr_driver; } __dpctl_give DPCTLPlatformVectorRef DPCTLPlatform_GetPlatforms() diff --git a/dpctl-capi/tests/test_sycl_device_manager.cpp b/dpctl-capi/tests/test_sycl_device_manager.cpp index 50df3ea8cf..b30705edb0 100644 --- a/dpctl-capi/tests/test_sycl_device_manager.cpp +++ b/dpctl-capi/tests/test_sycl_device_manager.cpp @@ -28,6 +28,7 @@ #include "dpctl_sycl_device_interface.h" #include "dpctl_sycl_device_manager.h" #include "dpctl_sycl_device_selector_interface.h" +#include "dpctl_utils.h" #include #include @@ -70,6 +71,14 @@ TEST_P(TestDPCTLDeviceManager, ChkPrintDeviceInfo) EXPECT_NO_FATAL_FAILURE(DPCTLDeviceMgr_PrintDeviceInfo(DRef)); } +TEST_P(TestDPCTLDeviceManager, ChkGetDeviceInfoStr) +{ + const char *info_str = nullptr; + EXPECT_NO_FATAL_FAILURE(info_str = DPCTLDeviceMgr_GetDeviceInfoStr(DRef)); + ASSERT_TRUE(info_str != nullptr); + EXPECT_NO_FATAL_FAILURE(DPCTLCString_Delete(info_str)); +} + TEST_P(TestDPCTLDeviceManager, ChkGetCachedContext) { DPCTLSyclContextRef CRef = nullptr;