将 std::vector<double> 从 C++ 包装到 C 以在 Swift 中使用

Posted

技术标签:

【中文标题】将 std::vector<double> 从 C++ 包装到 C 以在 Swift 中使用【英文标题】:wrapping std::vector<double> from C++ to C for use in Swift 【发布时间】:2018-10-03 20:51:26 【问题描述】:

我想在 Swift 4 中使用用 C++ 编写的程序。我已经阅读并理解了如何按照http://www.swiftprogrammer.info/swift_call_cpp.html 中的描述进行连接和包装的描述。

但是,现实生活更复杂,我没有 C++ 经验。我在 C++ 头文件中有以下代码。

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

我有两个问题:

    如何用C编写函数声明?我不知道向量在 C 中的等价物是什么。 C中命名空间是什么意思?

【问题讨论】:

C 中根本没有任何等价物。您可以围绕 std::vector 方法提供一组 C 包装函数,但这会非常乏味,而且您仍然可能会遇到很多问题的运行时问题。我建议你找一个用 C 写的向量库。 C Wrapper for C++。这将消除命名空间(C 中的这样的东西)。在调用 C++ 代码之前,C 样式函数必须将 c 样式数组作为参数(连同长度)并将其复制到 vector 您使用的库是否有其APIC 版本? 【参考方案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);

注意:完全未经测试的代码。

【讨论】:

以上是关于将 std::vector<double> 从 C++ 包装到 C 以在 Swift 中使用的主要内容,如果未能解决你的问题,请参考以下文章

带有 std::function<double(std::vector<double>) 回调的 cppyy

将 std::vector<double> 从 C++ 包装到 C 以在 Swift 中使用

使用 std::count_if() 时出现错误“没有从 'std::vector<double, std::allocator<double> >' 到 'double *'

使 double 和 std::vector<double> 协变

如何在初始化中将 'std::vector<double>' 转换为 'double'

使用“auto”代替 std::vector<double>*