C# std::complex wrappers marshalling by value

Change the wrapping to marshall directly to the .net
System.Numerics.Complex type instead of using an intermediate
std::complex .net type.
This commit is contained in:
William S Fulton 2017-05-19 08:15:01 +01:00
commit e11e1c4cb8

View file

@ -2,54 +2,67 @@
#include <complex>
%}
%fragment("SwigSystemNumericsComplex", "header") {
// Identical to the layout of System.Numerics.Complex, but does assume that it is
// LayoutKind.Sequential on the managed side
struct SwigSystemNumericsComplex {
double real;
double imag;
SwigSystemNumericsComplex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
};
}
namespace std {
%naturalvar complex;
// An extremely simplified subset of std::complex<> which contains just the
// methods we need.
template<typename T>
class complex
{
public:
complex(T re = T(), T im = T());
T real() const;
T imag() const;
};
} // namespace std
}
%define swig_complex_typemaps(T)
%typemap(cstype) std::complex<T>, const std::complex<T>& "System.Numerics.Complex"
%typemap(ctype, fragment="SwigSystemNumericsComplex") std::complex<T>, const std::complex<T> & "SwigSystemNumericsComplex"
%typemap(imtype) std::complex<T>, const std::complex<T> & "System.Numerics.Complex"
%typemap(cstype) std::complex<T>, const std::complex<T> & "System.Numerics.Complex"
// The casts in "pre" are needed in order to allow creating std::complex<float>
// from System.Numerics.Complex, which always uses doubles. It relies on the
// fact that the name of the C++ and C# float/double types are the same.
%typemap(csin,
pre=" var cpp$csinput = new Complex_" #T "((" #T ")$csinput.Real, (" #T ")$csinput.Imaginary);"
) std::complex<T>, const std::complex<T>& "Complex_" #T ".getCPtr(cpp$csinput)"
%typemap(in) std::complex<T>($*1_ltype temp), const std::complex<T> &($*1_ltype temp)
%{temp = std::complex< double >($input.real, $input.imag);
$1 = &temp;%}
%typemap(csout, excode=SWIGEXCODE) std::complex<T>, const std::complex<T>& {
Complex_##T cppret = new Complex_##T($imcall, $owner);$excode
return new System.Numerics.Complex(cppret.real(), cppret.imag());
%typemap(out) std::complex<T>
%{$result = SwigSystemNumericsComplex($1.real(), $1.imag());%}
%typemap(out) const std::complex<T> &
%{$result = SwigSystemNumericsComplex($1->real(), $1->imag());%}
%typemap(cstype) std::complex<T>, const std::complex<T> & "System.Numerics.Complex"
%typemap(csin) std::complex<T>, const std::complex<T> & "$csinput"
%typemap(csout, excode=SWIGEXCODE) std::complex<T>, const std::complex<T> & {
System.Numerics.Complex ret = $imcall;$excode
return ret;
}
%typemap(csvarin, excode=SWIGEXCODE2) const std::complex<T>& %{
%typemap(csvarin, excode=SWIGEXCODE2) const std::complex<T> & %{
set {
var cppvalue = new Complex_##T((T)value.Real, (T)value.Imaginary);
$imcall;$excode
}
%}
%typemap(csvarout, excode=SWIGEXCODE2) const std::complex<T>& %{
%typemap(csvarout, excode=SWIGEXCODE2) const std::complex<T> & %{
get {
var cppret = new Complex_##T($imcall, $owner);$excode
return new System.Numerics.Complex(cppret.real(), cppret.imag());
System.Numerics.Complex ret = $imcall;$excode
return ret;
}
%}
%template(Complex_##T) std::complex<T>;
%template() std::complex<T>;
%enddef
// By default, typemaps for both std::complex<double> and std::complex<float>