Reputation:
The project I am working on requires a bunch of translation from C++ concepts to C. In this use case, the caller is responsible for managing the memory buffer. He then calls the function and provides the array of type double and the amount of memory he allocated. Then the function fills his array buffer with all the doubles in the vector. This is my first shot at the function, but I am not sure if it is correct. Since I am not too familiar with C, I am sure there are mistakes. Am I doing this right? And how about adding the null terminating \0
at the end?
void getMoments(uint32_t & bufferSize,
double * moments)
{
if ( bufferSize < (vec.size() * sizeof(double)) + 1 )
{
// set error: bufferSize is not large enough to copy elements of vector.
}
typedef std::vector<double>::const_iterator it_type;
for (it_type it = vec.begin(); it != vec.end(); ++it)
{
double e = *it;
std::memcpy(moments, &e, sizeof(double));
}
// How do I add the null terminating \0?
}
By the way, the bufferSize is passed by reference because FORTRAN is one client and the language requires everything be passed by reference.
What confuses me about C arrays is the notion (or lack of notion) of a pointer. How do we know where we are at in the C array? In other words, every time I call memcpy should it write starting at the beginning of the array, thus overwriting my previously written bytes?
Upvotes: 0
Views: 607
Reputation: 19114
One possible solution:
#include <vector>
#include <algorithm>
...
int getMoments(uint32_t* bufferSize,
double * moments)
{
std::vector<double> vec = ...
if (*bufferSize/sizeof(double) < vec.size())
return -1;
std::copy(vec.begin(), vec.end(), moments);
return 0;
}
See also std::copy
Note: a "reference" is not available in C. Thus, your C API must pass parameter bufferSize as pointer.
Upvotes: 1
Reputation: 552
The pointer can be used as an output iterator:
if (bufferSize < vec.size() * sizeof(double))
{
// error: buffer too small
return;
}
std::copy(vec.begin(), vec.end(), moments);
Note: if you are passing a pointer to double, I would express the buffer/array size in terms of doubles as well, rather than chars (bytes).
Upvotes: 3
Reputation: 4199
I have no idea why you would ever need to null terminate array of doubles, so I removed it.
Full code:
void getMoments(uint32_t & bufferSize, double * moments)
{
if ( bufferSize < (vec.size() * sizeof(double)) )
{
// set error: bufferSize is not large enough to copy elements of vector.
}
typedef std::vector<double>::const_iterator it_type;
for (it_type it = vec.begin(); it != vec.end(); ++it)
{
*moments++ = *it;
}
}
Upvotes: 1