Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 std::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?

like image 569
Leeks and Leaks Avatar asked Jan 13 '10 15:01

Leeks and Leaks


2 Answers

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.

like image 163
Dmitry Avatar answered Oct 21 '22 16:10

Dmitry


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.

like image 24
missingfaktor Avatar answered Oct 21 '22 16:10

missingfaktor