Для проекта, над которым я работаю, требуется куча перевода из концепций C++ в C. В этом случае, вызывающий отвечает за управление буфером памяти. Затем он вызывает функцию и предоставляет массив типа double и объем памяти, который он выделял. Затем функция заполняет свой буфер массива всеми удвоениями в векторе. Это мой первый выстрел в функцию, но я не уверен, что это правильно. Поскольку я не очень хорошо знаком с C, я уверен, что есть ошибки. Правильно ли я это делаю? А как насчет добавления нулевого завершения \0
в конце?
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?
}
Кстати, bufferSize передается по ссылке, потому что FORTRAN - это один клиент, и язык требует, чтобы все передавалось по ссылке.
Что смущает меня в массивах C - это понятие (или отсутствие понятия) указателя. Как узнать, где мы находимся в массиве C? Другими словами, каждый раз, когда я вызываю memcpy, должен ли он писать, начиная с начала массива, таким образом перезаписывая мои ранее записанные байты?
Указатель может использоваться как выходной итератор:
if (bufferSize < vec.size() * sizeof(double))
{
// error: buffer too small
return;
}
std::copy(vec.begin(), vec.end(), moments);
Примечание: если вы передаете указатель на двойной, я бы добавил размер буфера/массива с точки зрения удвоений, а не символов (байтов).
double
можно использовать в качестве OutputIterator?
Я понятия не имею, почему вам когда-либо понадобится исключить массив двойников, поэтому я удалил его.
Полный код:
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;
}
}
\0
для строк C! Не двойные массивы. Мое отсутствие основ показывает, что :(
Одно из возможных решений:
#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;
}
См. Также std :: copy
Примечание: "ссылка" недоступна в C. Таким образом, ваш C API должен передать параметр bufferSize в качестве указателя.