0

Possible Duplicate:
std::vector<std::string> to char* array

I have to call a c function that accepts an array of string pointers. Example

void cFunction(char* cities[], int count)
 {
   for(int i = 0; i < count; ++i )
   {
    printf("%s\n", cities[i]);
   }
 }

Assume that function is in some third party libabry; it cannot be changed
I can declare a static array and call the function like this

char* placesA[] = {"Teakettle Junction", "Assawoman Bay", "Land O' Lakes", "Ion", "Rabbit Hask" };
cFunction(placesA, 5);


That works. But my data is dynamic i.e. the size of the array changes many times at runtime
So I tried this

std::vector<std::string> placesB(placesA, placesA + 5);
cFunction(&placesB[0], 5); // this won't work because std::string != char*[]


Tried this

std::vector<char*> placesC; 
cFunction(&placesC[0], 5);

I find placesC awkward to populate at the sametime avoid memory leaks
I am looking for a solution that is both efficient ( as little string copying as possible and preferably uses STL and or Boost )

Community
  • 1
  • 1
cabralP
  • 3
  • 1
  • @Bertrand Marron Not a duplicate. My source data does not have to be std::string. I used std::vector as one possible intermediate step in the solution – cabralP Aug 22 '11 at 20:21

2 Answers2

3

You can write a function that populates a vector<char*> from a vector<string> using .c_str() on each string.

Eran Zimmerman Gonen
  • 4,375
  • 1
  • 19
  • 31
  • And then you can pass `&charvec[0]` to the `cFunction()`. – wilx Aug 22 '11 at 20:18
  • That requires a `const_cast` but with a bit of care on the callee’s site this works. – Konrad Rudolph Aug 22 '11 at 20:18
  • 1
    Using `&the_string[0]` won't require the `const_cast` (assuming a non-const view of the vector), but requires C++0x as C++03 doesn't make the guarantee that the elements of `std::basic_string` are contiguous in memory. – Luc Danton Aug 22 '11 at 20:21
1

There's going to be some awkwardness no matter how you slice it. If the C API truly requires modifiable arrays, then that's what you'll need to provide -- you'll have to copy your strings into. If it doesn't modify the strings, then you can use a std::vector of const char*, where the string data is still owned by the underlying std::string objects; you just have to be careful that the C API doesn't hold onto references to those strings and tries to access them after the strings have been modified or deallocated.

For example, here's one way to do it:

// Unary functor which calls c_str() on a std::string object
struct StdStringCStrFunctor
{
    const char *operator() (const std::string& str) { return str.c_str(); }
};
...

std::vector<std::string> places;
... // populate places

// Convert to array of C strings
std::vector<const char *> placesCStr(places.size());
std::transform(places.begin(), places.end(), placesCStr.begin(), StdStringCStrFunctor());
cFunction(const_cast<char**>(&placesCStr[0]), placesCStr.size());
Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589