3

I'm adding a C++ front-end to a C library. One function in this library calls back to a handler with an array and an integer with the size of the array. Therefore you must provide a C function,

int handler(int argc, sometype **argv);

Now, I'd like to allow the C++ calling code to provide a more C++ish handler function, something like,

int handler(std::vector<sometype*> args);

Changing the handler type isn't hard, I just have to provide my own handler which then calls the user-provided handler. So I need to create an std::vector and copy the contents of argv into it.

However, I don't really want to copy the entire list of pointers if possible. Unfortunately I think it's not possible to tell std::vector to use an already-allocated block of memory for its internal array, and moreover the array is static, and should be considered const.

Is there some STL type similar to std::vector that can be used to wrap pre-allocated C-style arrays with a more friendly interface? It should support size query and iteration, similar to std::vector.

Thanks.

4
  • An intrusive array reference wrapper? Not in the standard library, but easy enough to write yourself... people have been asking for a string_ref type for ages... Commented Sep 6, 2012 at 16:23
  • There's no standard container that will do this for you, as far as I'm aware. Perhaps Boost might help, but I'm not familiar with it. Writing your own container shouldn't be too hard, however! I will note that std::vector is not an appropriate concept for wrapping a fixed-length array; vectors may grow and shrink which an array cannot. Commented Sep 6, 2012 at 16:25
  • +1 encapsulating array primitve type for a more encapsulating, maybe object oriented collection Commented Sep 6, 2012 at 16:31
  • @Rook: yeah, std::array is probably closer to what I'm looking for. Commented Sep 6, 2012 at 16:44

4 Answers 4

1

Have you thought about making your function take a pair of iterators instead of a container? You would have to make it a template function, so I can understand why that may not work as well as you would like, but it would let you pass in the array.

template<typename I>
int handler(I begin, I end);

handler(argv, &argv[argc]);

It's still not a perfect solution, but it would be a touch more generic and allow for you to use the preexisting array.

Sign up to request clarification or add additional context in comments.

Comments

1

I'm not certain what you're asking, but If I was given this function prototype

int handler(int argc, const sometype *const *argv);

Here's make a C++ wrapper:

int handler(const std::vector<sometype*>& arg) 
{return handler(arg.size(), &arg[0]);} //no copies

template<class const_iterator>
int handler(const_iterator begin, const_iterator end) //can pass any structure
{return handler(std::distance(begin, end), &*begin);} //no copies

Here's how I would implement this API in C++:

int handler(int argc, const sometype *const*argv) {
    const std::vector<const sometype*> arg(argv, argv+argc); //this will copy the pointers
    //stuff
}

Unfortunately, there's no way to get an existing array into a vector, but is copying a few pointers really slow enough to care about?

Proof of compilation: http://ideone.com/BkSVd

2 Comments

Right, but that copies my immutable data into a mutable container. It works, but I'm wondering if there's something that doesn't require copying.
wait, which data is supposed to be immutable? In that function signature, everything is mutable, there's no const anywhere. Oh! I see it. I added const to the signatures, problem solved.
0

Well, I'm sure if you know about ::vector, you've looked into ::array?

http://www.cplusplus.com/reference/stl/array/

However, the main problem - overlaying objects onto existing memory - reminds me of simple packet sniffers: create the object structure, then overlay it by moving its reference over the known data. I'm not sure if you can do this in your problem, but that'd be the first avenue I'd consider.

Note: I don't know exactly how a std::array is laid out so obviously that would be difficult to implement :/

9 Comments

Both std::array and std::vector are laid out as a contiguous slab of memory; getting the address of the first element of a vector by doing a &myvector[0] will get you a pointer you can use as a plain C array. This means you can memcpy into and out of appropriately sized vectors and array objects.
The biggest downside to std::array is that you need to pass the size as part of the template parameters, makes it less then ideal for a variable sized array.
@FoxCutter yes, you're right. I guess my assumption that as he was dealing with a C array was that the size requirement would remain the same, which is obviously false. Maybe some more info on the issue could clarify that. Apart from that, would my proposed solution work to simply overlay the std::array? (and given Rook's info, wouldn't a vector overlay also work?)
@AkshayaAnnavajhala Yes, other then the size thing it would work just fine. I often use std::vector in place of doing an array new, just keeps the code tidy, it's easy to pass to C code and API, and in release build the iterators are just pointers, so it's fast.
Yeah, std::array is probably exactly what I'm looking for, but is it possible to tell it to use my array directly rather than allocating it itself? Also, is there such thing as an immutable std::array? (Some kind of const variation?)
|
0

What type of data is going to be referenced by those pointer elements ?

Who is the owner of those pointer elements, I mean, are those elements just referenced by the collection / data structure, or is that collection in charge of allocating, deallocating those items ?

Are those items equal type or equal size ?

For example, array of characters of different size, or objects that may be different base class, but descend from a common ancestor.

All these topics maybe considered to decide which library, object oriented or not, and which data structure or collection to use.

Seems std and Boost should be first option to lookup first. But, sometimes, you may have to built your own collection.

Your library seems to require more like an indexable List concept than an Array, altought, sometimes are interchangable.

Cheers.

2 Comments

Sorry for the ambiguity. The array provided to the handler is considered "not to be touched", and "size" does not change. I just want to wrap it up so that the C++ user sees an STL-like interface.
@Steve It makes sense since its a parameter collection, more than indexable read-only list

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.