Currently we have the followring situation:
- The standard library doesn't specifiy complex types.
- Operator overloading makes it very easy to specify complex types in libraries
- Different Libaries define their own Version of Complex types
- The widely use num-complex crates definies a generic Complex
- It is very easy to design a complex number type compatible to C in memory. I believe all of these are valid points that should be upheld.
However currently there are no C ABI compatible complex types in Rust, that can be used to call functions e.g. from cmath.h
One solution would be to introduce special traits and impl Trait
parameters are translated into C-ABI compatible parameter passes.
This means:
- Introduce two new traits, with lang-items into the
core
library:
#[lang = "complex_single"]
pub trait ComplexSingle {
fn into_array(self) -> [f32; 2];
fn from_array([f32; 2]) -> Self;
}
#[lang = "complex_double"]
pub trait ComplexDouble {
fn into_array(self) -> [f64; 2];
fn from_array([f64; 2]) -> Self;
}
- Extend the
extern "C"
calling convention: Whenever animpl ComplexSingle
parameter is encountered, Rust will useComplexSingle::into_array()
to convert the Complex Number into a[f32; 2]
and pass it ABI compatible to the_Complex float
C data type (The[0]
entry specifies real, the[1]
entry the imaginary part). Whenimpl ComplexSingle
is used as return value, the return value is interpreted as a[f32; 2]
that is then passed toComplexSingle::from_array()
before being returned to user code. In a similar fashionimpl ComplexDouble
is used for parameters and return values ABI compatible to the_Complex double
C data type.
A C function:
double _Complex csin(double _Complex z);
can be declared in Rust using:
use core::ffi::ComplexDouble;
extern "C" {
csin(impl ComplexDouble) -> impl ComplexDouble;
}