4

I want to use a program which is written in C++ in Swift 4. I already read and understood the description how to do the briding and wrapping as described in http://www.swiftprogrammer.info/swift_call_cpp.html.

However, real life is more complicated and I have no experience in C++. I have the following piece of code in the C++ header file.

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

I have two questions:

  1. How to write the function declaration in C? I have no idea what the equivalent of vector is in C.
  2. What is the meaning of namespace in C?
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Heinz M.
  • 668
  • 3
  • 8
  • 3
    There simply isn't any equivalent in C. You could provide a set of C wrapper functions around the std::vector methods, but that would be quite tedious and you'll still likely run into lots of run-time issues. I suggest you look for a vector library that is written in C. – jwdonahue Oct 03 '18 at 20:54
  • [C Wrapper for C++](https://stackoverflow.com/questions/7691035/c-wrapper-for-c). This will eliminate the namespace (so such thing in C). The C-style function will have to take a c-style array as a parameter (along with the length) and copy it into the `vector` before calling the C++ code. – user4581301 Oct 03 '18 at 21:01
  • Does the library you are using have a `C` version of its `API`? – Galik Oct 03 '18 at 22:03

1 Answers1

3

You can write some bridging functions that use C compatible types to call C++ functions. This is very untested code just to give you an idea what you could do:

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"

If you compile that as C++ the extern "C" {} block will make it so you can call those functions from C.

You could write a C program a bit like this for example:

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);

Note: Completely untested code.

Galik
  • 47,303
  • 4
  • 80
  • 117