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

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

Often you call this in a loop, for example, to read data from a stream or channel. In the end, I would like to efficiently return a string containing the full data from all callbacks to retrieve this data. I thought to use std::string , as it is + = optimized similarly to the Java or C # StringBuffer.append() / StringBuilder.Append() , preferring speed over memory.

But I'm not sure how best to combine the std::string functions with Win32, since for starters these functions take char[] . Any suggestions?

+7
c ++ string stl winapi
source share
4 answers

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

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

eg. Let ss be a std::string instance, and sc be a string of type C, then 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 the UNICODE macro is specified, then the lines will be wchar_t* , and so you will have to use std::wstring .

+6
source share

If the argument is for 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:

 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 for output only , also use std::vector<Type> as follows:

 // 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 necessary.

You can read more on this topic in Scott Meyers' Effective STL Book.

+11
source share

Instead of std :: string, I would suggest using std::vector and using &v.front() when using v.size() . Make sure the space is 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 
+6
source share
  • You need a compatible string type: typedef std::basic_string<TCHAR> tstring; - a good choice.

  • To enter 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 continuous storage like std :: vector. However, all the std :: basic_string implementations I've seen use continuous storage, and the C ++ standards committee considers the missing warranty a defect in the standard. The defect was fixed in a C ++ 0x project.

If you are ready to bend the rules so easily - without any negative consequences, you can use & (* aString.begin ()) as a pointer to the TCHAR buffer of aString.size () length. Otherwise, you are stuck with std :: vector.

Here, what the C ++ standard committee has to say about continuous string storage:

Not standardizing this existing practice does not give developers more freedom. We thought it might be ten years ago. But suppliers spoke of both their implementation and their voice at IWG meetings. implementations will be continuous, regardless of what the standard says. Thus, a standard could also give lower-case customers more design choices.

+2
source share