Call C++ function with complex parameters and complex return type out of C code

Viewed 1370

I have a C++ mathematical library and writing a project in Rust. Since it is not possible to call C++ directly from Rust, but to call C is possible, I decided to write a standard wrapper from C++ into C.

Everything is working more or less as expected except of functions which have complex parameters, where the imaginary part is lost for some reason. Below I provide mwe.

export_c++.h

#ifdef __cplusplus
#include <complex>
std::complex<double> foo(const std::complex<double> a);
#endif

#ifdef __cplusplus
extern "C" {
#endif

#include <complex.h>

double _Complex c_foo(const double _Complex a);

#ifdef __cplusplus
}
#endif

export_c++.cc

#include "export_c++.h"

#include <iostream>

std::complex<double> foo(const std::complex<double> a){
    return a;
}

double _Complex c_foo(const double _Complex a){
    std::complex<double> b{a};
    double _Complex res{b.real(), b.imag()};

    return res; 
}

now we compile this as

g++ -c -std=gnu++11 -o export_c++.o export_c++.cc

and assemble into library

ar rcs libexport_c++.a export_c++.o

and we will use it in main.c

#include "export_c++.h"

#include <stdio.h>

int main(int argc, char *argv[])
{
    double complex a = 1. + I * 1.;
    double complex b = c_foo(a);
    printf("a = %f + I %f\n", creal(a), cimag(a));
    printf("b = %f + I %f\n", creal(b), cimag(b));
    return 0;
}

Compile main.c

gcc -o main -L. -lexport_c++ main.c

and run

./main

which yields

a = 1.000000 + I 1.000000
b = 1.000000 + I 0.000000

I use macOS and compile with

Apple LLVM version 8.1.0 (clang-802.0.42)

Also these two questions are somewhat relevant to the question identifier "creal" is undefined - seen on Mac but not on Linux and c++ and <complex.h> with <complex> in separate files

Of course, as a workaround I can split the complex parameters into two double ones, since in any case I would call the code out of rust.

By the way, compilation with gcc 7.1.0

g++-7 -c -std=gnu++11 -o export_c++.o export_c++.cc
ar rcs libexport_c++.a export_c++.o
gcc-7 -o main -L. -lexport_c++ -lstdc++ main.c

produces expected result

a = 1.000000 + I 1.000000
b = 1.000000 + I 1.000000
1 Answers
Related