Last time, we saw that passing a C++ std::[w]string_view to a C-interface API (like Win32 APIs) expecting a C-style null-terminated string pointer can cause subtle bugs, as there is a requirement impedance mismatch. In fact:
- The C-interface API (e.g. Win32 SetWindowText) expects a null-terminated string pointer
- The STL string views do not guarantee null-termination
So, supposing that you have a C++17 (or newer) code base that heavily uses string views, when you need to interface those with Win32 API function calls, or whatever C-interface API, expecting C-style null-terminated strings, how can you safely pass instances of string views as input parameter?
Invoking the string_view/wstring_view’s data method would be dangerous and source of subtle bugs, as the data returned pointer is not guaranteed to point to a null-terminated string.
Instead, you can use a std::string/wstring object as a bridge between the string views and the C-interface API. In fact, the std::string/wstring’s c_str method does guarantee that the returned pointer points to a null-terminated string. So it’s safe to pass the pointer returned by std::[w]string::c_str to a C-interface API function that expects a null-terminated C-style string pointer (like PCWSTR/LPCWSTR parameters in the Win32 realm).
For example:
// sv is a std::wstring_view
// C++ STL strings can be easily initialized from string views
std::wstring str{ sv };
// Pass the intermediate wstring object to a Win32 API,
// or whatever C-interface API expecting
// a C-style *null-terminated* string pointer.
DoSomething(
// PCWSTR/LPCWSTR/const wchar_t* parameter
str.c_str(), // wstring::c_str
// Other parameters ...
);
// Or use a temporary string object to wrap the string view
// at the call site:
DoSomething(
// PCWSTR/LPCWSTR/const wchar_t* parameter
std::wstring{ sv }.c_str(),
// Other parameters ...
);