开发者

How to mix std::string with Win32 functions that take char[] buffers?

There are a number of Win32 functions that take the address of a buffer, such as TCHAR[256], and write some data to that buffer. It may be less than the size of the buffer or it may be the entire buffer.

Often you'll call this in a loop, for example to read data off a stream or pipe. In the end I would like to efficiently return a string that has the complete data from all the iterated calls to retrieve this data. I had been thinking to use 开发者_如何学Gostd::string since it's += is optimized in a similar way to Java or C#'s StringBuffer.append()/StringBuilder.Append() methods, favoring speed instead of memory.

But I'm not sure how best to co-mingle the std::string with Win32 functions, since these functions take the char[] to begin with. Any suggestions?


If the argument is input-only use std::string like this

std::string text("Hello");
w32function(text.c_str());

If the argument is input/output use std::vector<char> instead like this:

std::string input("input");
std::vector<char> input_vec(input.begin(), input.end());
input_vec.push_back('\0');
w32function(&input_vec[0], input_vec.size());
// Now, if you want std::string again, just make one from that vector:
std::string output(&input_vec[0]);

If the argument is output-only also use std::vector<Type> like this:

// allocates _at least_ 1k and sets those to 0
std::vector<unsigned char> buffer(1024, 0);
w32function(&buffer[0], buffer.size());
// use 'buffer' vector now as you see fit

You can also use std::basic_string<TCHAR> and std::vector<TCHAR> if needed.

You can read more on the subject in the book Effective STL by Scott Meyers.


std::string has a function c_str() that returns its equivalent C-style string. (const char *)

Further, std::string has overloaded assignment operator that takes a C-style string as input.

e.g. Let ss be std::string instance and sc be a C-style string then the interconversion can be performed as :

ss = sc; // from C-style string to std::string
sc = ss.c_str(); // from std::string to C-style string

UPDATE :

As Mike Weller pointed out, If UNICODE macro is defined, then the strings will be wchar_t* and hence you would have to use std::wstring instead.


Rather than std::string, I would suggest to use std::vector, and use &v.front() while using v.size(). Make sure to have space already allocated!

You have to be careful with std::string and binary data.

s += buf;//will treat buf as a null terminated string
s += std::string(buf, size);//would work


  • You need a compatible string type: typedef std::basic_string<TCHAR> tstring; is a good choice.

  • For input only arguments, you can use the .c_str() method.

  • For buffers, the choice is slightly less clear:

std::basic_string is not guaranteed to use contiguous storage like std::vector is. However, all std::basic_string implementations I've seen do use contiguous storage, and the C++ standards committee consider the missing guarantee to be a defect in the standard. The defect has been corrected in the C++0x draft.

If you're willing to bend the rules ever so slightly - with no negative consequences - you can use &(*aString.begin()) as a pointer to a TCHAR buffer of length aString.size(). Otherwise, you're stuck with std::vector for now.

Here's what the C++ standard committee have to say about contiguous string storage:

Not standardizing this existing practice does not give implementors more freedom. We thought it might a decade ago. But the vendors have spoken both with their implementations, and with their voice at the LWG meetings. The implementations are going to be contiguous no matter what the standard says. So the standard might as well give string clients more design choices.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜