перенос std::vector‹double› из C++ в C для использования в Swift

Я хочу использовать программу, которая написана на C++ в Swift 4. Я уже прочитал и понял описание того, как сделать сборку и упаковку, как описано в http://www.swiftprogrammer.info/swift_call_cpp.html..

Однако реальная жизнь сложнее, и у меня нет опыта работы с C++. У меня есть следующий фрагмент кода в заголовочном файле C++.

namespace Fft {
   void transform(std::vector<double> &real, std::vector<double> &imag);
}

У меня есть два вопроса:

  1. Как написать объявление функции на C? Я понятия не имею, что эквивалентно вектору в C.
  2. Что означает пространство имен в C?

person Heinz M.    schedule 03.10.2018    source источник
comment
В C просто нет эквивалента. Вы могли бы предоставить набор функций-оболочек C вокруг методов std::vector, но это было бы довольно утомительно, и вы все равно столкнетесь с множеством проблем во время выполнения. Я предлагаю вам поискать векторную библиотеку, написанную на C.   -  person jwdonahue    schedule 03.10.2018
comment
C-оболочка для C++. Это устранит пространство имен (так в C). Функция в стиле C должна будет принять массив в стиле c в качестве параметра (вместе с длиной) и скопировать его в vector перед вызовом кода C++.   -  person user4581301    schedule 04.10.2018
comment
Используемая вами библиотека имеет C версию своей API?   -  person Galik    schedule 04.10.2018


Ответы (1)


Вы можете написать несколько связующих функций, которые используют C совместимые типы для вызова C++ функций. Это очень непроверенный код, просто чтобы дать вам представление о том, что вы можете сделать:

namespace Fft {
   void transform(std::vector<double> &real, std::vector<double> &imag);
}

extern "C" {

struct complex_vector
{
    void* real;
    void* imag;
};

complex_vector create_complex_vector(size_t size)
{
    complex_vector cv;
    cv.real = new std::vector<double>(size);
    cv.imag = new std::vector<double>(size);
    return cv;
}

void complex_vector_push_back(complex_vector cv, double real, double imag)
{
    reinterpret_cast<std::vector<double>*>(cv.real)->push_back(real);
    reinterpret_cast<std::vector<double>*>(cv.imag)->push_back(imag);
}

void complex_vector_reserve(complex_vector cv, size_t size)
{
    reinterpret_cast<std::vector<double>*>(cv.real)->reserve(size);
    reinterpret_cast<std::vector<double>*>(cv.imag)->reserve(size);
}

void complex_vector_resize(complex_vector cv, size_t size)
{
    reinterpret_cast<std::vector<double>*>(cv.real)->resize(size);
    reinterpret_cast<std::vector<double>*>(cv.imag)->resize(size);
}

void fill_complex_vector(complex_vector cv, double* real, double* imag)
{
    auto v_real = reinterpret_cast<std::vector<double>*>(cv.real)->data();
    auto v_imag = reinterpret_cast<std::vector<double>*>(cv.imag)->data();
    auto v_size = reinterpret_cast<std::vector<double>*>(cv.real)->size();

    std::copy(real, real + v_size, v_real);
    std::copy(imag, imag + v_size, v_imag);
}

void fft_transform(complex_vector cv)
{
    Fft::transform(*reinterpret_cast<std::vector<double>*>(cv.real), *reinterpret_cast<std::vector<double>*>(cv.imag));
}

double* complex_vector_real_array(complex_vector cv)
{
    return reinterpret_cast<std::vector<double>*>(cv.real)->data();
}

double* complex_vector_imag_array(complex_vector cv)
{
    return reinterpret_cast<std::vector<double>*>(cv.imag)->data();
}

size_t complex_vector_size(complex_vector cv)
{
    return reinterpret_cast<std::vector<double>*>(cv.imag)->size();
}

void destroy_complex_vector(complex_vector cv)
{
    delete reinterpret_cast<std::vector<double>*>(cv.real);
    delete reinterpret_cast<std::vector<double>*>(cv.imag);
}

} // extern "C"

Если вы скомпилируете это как C++, блок extern "C" {} сделает так, что вы сможете вызывать эти функции из C.

Например, вы можете написать программу C примерно так:

complex_vector cv = create_complex_vector(1024);

// fill the vector
for(int i = 0; i < complex_vector_size(cv); ++i)
    complex_vector_push_back(cv, 0.2 * i, 0.4 * i);

// call the transform
fft_transform(cv);

double* real = complex_vector_real_array(cv);
double* imag = complex_vector_imag_array(cv);
size_t size = complex_vector_size(cv);

// use your transformed data here ...

destroy_complex_vector(cv);

Примечание. Полностью непроверенный код.

person Galik    schedule 03.10.2018