C ++ function call with complex parameters and complex return type from C code

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

Everything works more or less as expected, except for functions that have complex parameters, where for some reason the imaginary part is lost. 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 ++. Ss

#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 will compile it as

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

and get together in the 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

what gives

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)

"creal" undefined - Mac, Linux ++ < complex.h > <complex>

, double, .

, 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

a = 1.000000 + I 1.000000
b = 1.000000 + I 1.000000
+4
1

:

export_++.

//
// c and c++
//
struct complex_proxy
{
    double real;
    double imaginary;
};

#ifdef __cplusplus
extern "C" {
#endif

struct complex_proxy proxy_foo(struct complex_proxy a);

#ifdef __cplusplus
}
#endif

//
// c++ only
//
#ifdef __cplusplus
#include <complex>

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

#else

#include <complex.h>

double _Complex c_foo(const double _Complex a);

#endif

export_++. CPP

#include "export_c++.h"

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


struct complex_proxy proxy_foo(struct complex_proxy a)
{
    auto result = foo({a.real, a.imaginary});
    return { result.real(), result.imag() };
}

export_++.

#include "export_c++.h"

double _Complex c_foo(const double _Complex a)
{

    struct complex_proxy a_proxy = { creal(a), cimag(a) };
    struct complex_proxy result = proxy_foo(a_proxy);
    return result.real + result.imaginary * I;
}
0

Source: https://habr.com/ru/post/1677488/


All Articles