2

Is there is a way/trick to pass std::set to a C API which expects C Array?

Eran
  • 21,632
  • 6
  • 56
  • 89
AshokS
  • 63
  • 2

3 Answers3

11

Not directly, but you can first convert the set to a vector (called, say, vec), and then pass &vec[0], which is a pointer to the first element of the internal vector array.

With C++11, you can pass vec.data() instead of &vec[0].

Community
  • 1
  • 1
Eran
  • 21,632
  • 6
  • 56
  • 89
3

No, but you could fill an array with your set contents pretty quickly. For example, assuming mySet is a set of the same type as YOUR_TYPENAME:

YOUR_TYPENAME arr* = new YOUR_TYPENAME[mySet.size()];
std::copy(mySet.begin(), mySet.end(), arr);

Then just pass arr into the C API.

John Humphreys
  • 37,047
  • 37
  • 155
  • 255
  • 4
    Why would you use `new` when you could use `vector`? – Mark Ransom Oct 03 '11 at 15:09
  • 1
    +1. I like this solution more than the `vector` one, because it does not require an intermediary type. *But*, as you are dealing with a C API I'd allocate the array with `malloc` (or a derivate), especially if the array is likely to be `free`d inside the API. – Constantinius Oct 03 '11 at 15:09
  • 2
    @Constantinius, I agree that `malloc` would be more appropriate than `new` if the ownership was passed to the API, but I wouldn't expect that to be a common case. Not sure what you mean by an intermediary type, in both cases you're creating an array of the element type. `vector` leaves you with fewer memory management issues, especially if there's any chance that an exception might be thrown somewhere. – Mark Ransom Oct 03 '11 at 15:21
  • 2
    @Constantinius: What does "require an intermediary type" have to do with anything? Guess what: `new YOUR_TYPENAME[...]` has a type too! `std::vector` is more appropriate. The question says nothing about `free`'ing. – GManNickG Oct 03 '11 at 15:26
  • I prefer not to pass vectors into C functions even though it's really just contiguous memory either way (I've actually seen non-standard compliant vector implementations on some embedded OS's, so I don't like to rely on the vector being contiguous) - but I do agree malloc would be a better thing to use given we're working with C :) – John Humphreys Oct 03 '11 at 15:27
  • 2
    @Constantinius, this is purely academic since we don't know the specifics of the API, but in general, if the API is going to free memory you allocate, it _must_ specify exactly how should you allocate it. `malloc` and `free` won't do much good if two CRTs happen to be used (and obviously, neither will `new` and `delete`). So in case of memory ownership transfer across API boundaries, there are no best practices - just strict definitions (given you can't change the API). – Eran Oct 03 '11 at 16:23
1

For completeness, the vector alternative to the currently accepted answer would look like this:

{
  std::vector<YOUR_TYPENAME> arr(mySet.begin(), mySet.end());
  Your_C_API(&arr[0]);
  // memory implicitly freed on next line
}

I prefer this style because:

  • It takes one fewer lines, and
  • It eliminates a class of mistakes that I often make (that is, forgetting to delete).
Robᵩ
  • 163,533
  • 20
  • 239
  • 308