C++: using std::wstring in API function
Question
I'm using the SHGetSpecialFolderLocation API function. My application is set to "Use Unicode Character Set".
Here's what I have so far:
int main ( int, char ** )
{
LPITEMIDLIST pidl;
HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL, &pidl);
/* Confused at this point */
wstring wstrPath;
wstrPath.resize ( _MAX_PATH );
BOOL f = SHGetPathFromIDList(pidl, wstrPath.c_str () );
/* End confusion */
The error I'm getting is:
error C2664: 'SHGetPathFromIDListW' : cannot convert parameter 2 from 'const wchar_t *' to 'LPWSTR'
Can someone help? What's the proper C++ way to do this?
Thanks!
Solution
The second parameter is an out parameter, so you can't just pass c_str
(which is const
) directly. It would probably be simplest just to do:
wchar_t wstrPath[MAX_PATH];
BOOL f = SHGetPathFromIDList(pidl, wstrPath);
MAX_PATH
is currently 260 characters.
OTHER TIPS
wstring::c_str()
returns const wchar_t*
and is read only. LPWSTR
is not a const
type, and that parameter is an out parameter. You will need to allocate the buffer yourself. You could do something like this:
wchar_t buf[MAX_PATH] = {0};
BOOL f = SHGetPathFromIDList( pidl, buf );
wstring wstrPath = buf;
You can get address of 1st array item in basic_string as pointer to writable string data. Although C++ standard does not guarantee that this block of memory must be continuous this is safe in all known implementations (How bad is code using std::basic_string as a contiguous buffer).
std::wstring path(_MAX_PATH, L'\0');
BOOL f = SHGetPathFromIDList(pidl, &path[0]);
std::basic_string::c_str()
returns a constant buffer to it's memory. If you want to modify the string, you'd have to do something like this:
wstring wstrPath;
wstrPath.resize( MAX_PATH );
BOOL f = SHGetPathFromIDList(pidl, &wstrPath[0]);
wstrPath.erase(
std::find(wstrPath.begin(), wstrPath.end(), L'\0'), wstrPath.end()
); //Throw away unused buffer space
EDIT: This should also work if you're not afraid of C libraries (though I've not tested it like I've tested the implementation above):
wstring wstrPath;
wstrPath.resize( MAX_PATH );
BOOL f = SHGetPathFromIDList(pidl, &wstrPath[0]);
wstrPath.resize(wcslen(wstrPath.c_str()));
wstring::c_str() does not let you modify its internal buffer in this way. Your easiest workaround is to create a wchar_t buffer yourself, and the pass that to the wstring constructor:
wchar_t buf[MAX_PATH];
BOOL f = SHGetPathFromIDList(pidl, buf );
wstring wstrPath(buf);