I have a vector<std::string>
variable. I need to pass it onto a method which accepts char**
as an input parameter.
how to do this ? If possible I need to pass a writable one.
Update 1: In a tool for creating a service method, i give parameters as std::vector, but it sets automatically the qualifier as &, which means my method definition generated by the tool will look as:
std::string SvcImpl::myMethodname ( const std::string par1, const std::vector< std::string >& par2, const std::vector< std::string >& par3 ) { }
This method gets called automatically with values in the patameter passed. Now from inside this method I'm going to call a method in a dll in a lib folder which looks like:
int method_to_be_called(char* par1, char ** par2, char ** par3, void* pRetValue);
for par1 --> I'm passing (char*)par1.c_str()
I need to know how to pass variables for par2 and par3 and for pRetValue. values for par2 and par3 are available in vector but the last parameter pRetValue is an output parameter that i need to return it as std::string.
sorry if i am very confusing or asking very basic questions.
Galik's answer has a number of safety issues. Here is how I would do it in Modern C++:
#include <iostream> #include <string> #include <vector> void old_func(char** carray, std::size_t size) { for(std::size_t i(0); i < size; ++i) std::cout << carray[i] << '\n'; } void other_old_func(const char** carray, std::size_t size) { for(std::size_t i(0); i < size; ++i) std::cout << carray[i] << '\n'; } int main() { { std::cout << "modifiable version\n"; std::vector<std::string> strings{"one", "two", "three"}; std::vector<char*> cstrings{}; for(auto& string : strings) cstrings.push_back(&string.front()); old_func(cstrings.data(), cstrings.size()); std::cout << "\n\n"; } { std::cout << "non-modifiable version\n"; std::vector<std::string> strings{"four", "five", "six"}; std::vector<const char*> cstrings{}; for(const auto& string : strings) cstrings.push_back(string.c_str()); other_old_func(cstrings.data(), cstrings.size()); std::cout << std::endl; } }
No messy memory management or nasty const_cast
s.
Live on Coliru.
Outputs:
modifiable version one two three non-modifiable version four five six
It is possible to solve the problem without copying out all the std::strings
as long as the function does not modify the passed in char**
. Otherwise I can see no alternative but to copy out everything into a new char**` structure (see second example).
void old_func(char** carray, size_t size) { for(size_t i = 0; i < size; ++i) std::cout << carray[i] << '\n'; } int main() { std::vector<std::string> strings {"one", "two", "three"}; std::vector<char*> cstrings; cstrings.reserve(strings.size()); for(size_t i = 0; i < strings.size(); ++i) cstrings.push_back(const_cast<char*>(strings[i].c_str())); // Do not change any of the strings here as that will // invalidate the new data structure that relies on // the returned values from `c_str()` // // This is not an issue after C++11 as long as you don't // increase the length of a string (as that may cause reallocation) if(!cstrings.empty()) old_func(&cstrings[0], cstrings.size()); }
EXAMPLE 2: If the function must modify the passed in data:
void old_func(char** carray, size_t size) { for(size_t i = 0; i < size; ++i) std::cout << carray[i] << '\n'; } int main() { { // pre C++11 std::vector<std::string> strings {"one", "two", "three"}; // guarantee contiguous, null terminated strings std::vector<std::vector<char>> vstrings; // pointers to rhose strings std::vector<char*> cstrings; vstrings.reserve(strings.size()); cstrings.reserve(strings.size()); for(size_t i = 0; i < strings.size(); ++i) { vstrings.emplace_back(strings[i].begin(), strings[i].end()); vstrings.back().push_back('\0'); cstrings.push_back(vstrings.back().data()); } old_func(cstrings.data(), cstrings.size()); } { // post C++11 std::vector<std::string> strings {"one", "two", "three"}; std::vector<char*> cstrings; cstrings.reserve(strings.size()); for(auto& s: strings) cstrings.push_back(&s[0]); old_func(cstrings.data(), cstrings.size()); } }
NOTE: Revised to provide better code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With