[英]How do you pass Fortran's complex type to C#?
Suppose I have the following Fortran code假设我有以下 Fortran 代码
subroutine COMPLEX_PASSING(r, i, c)
!DEC$ ATTRIBUTES DLLEXPORT::COMPLEX_PASSING
REAL*8 :: r, i
COMPLEX*8 :: c
c = cmplx((r * 2), (i * 2))
return
end
Fortran code was compiled with Fortran 代码编译用
gfortran -c complex_passing.f90
gfortran -fPIC -shared -o complex_passing.dll complex_passing.o
How would I call this subroutine in C#?我如何在 C# 中调用这个子程序? I have tried the following code:
我尝试了以下代码:
using System;
using System.Runtime.InteropServices;
namespace FortranCalling {
class Program {
static void main(string[] args) {
double real = 4;
double imaginary = 10;
COMPLEX c = new COMPLEX();
complex_passing( ref real, ref imaginary, ref c);
Console.WriteLine("Real: {0}\nImaginary: {1}", c.real, c.imaginary);
Console.ReadLine();
}
[StructLayout(LayoutKind.Sequential)]
struct COMPLEX {
public double real;
public double imaginary;
}
[DllImport("complex_passing.dll", EntryPoint = "complex_passing_", CallingConvention = CallingConvention.Cdecl)]
static extern void complex_passing(ref double r, ref double i, ref COMPLEX c);
}
}
With little success - my COMPLEX struct seems to be returning garbage data:收效甚微 - 我的 COMPLEX 结构似乎正在返回垃圾数据:
Real: 134217760.5
Imaginary: 0
When I would expect the real part to be 8 and the imaginary part to be 20.当我期望实部是 8 而虚部是 20 时。
gfortran treats the non-standard COMPLEX*8
as a complex of size 8 bytes, with real and imaginary components 4 bytes each. gfortran 将非标准
COMPLEX*8
视为大小为 8 字节的复数,实部和虚部各 4 字节。 You instead require a complex of 16 bytes, with real and imaginary components of 8 bytes each ( COMPLEX*16
) or you should change the C# side accordingly.相反,您需要一个 16 字节的复数,实部和虚部各有 8 个字节(
COMPLEX*16
),或者您应该相应地更改 C# 端。
The effect of this is visible with the following under gfortran:在 gfortran 下可以看到以下效果:
complex*8 :: c8 = (8d0, 20d0)
complex*16 :: c16 = 0
c16%re = TRANSFER(c8,c16)
print*, c8, c16
end
Of course, you shouldn't be using complex*
at all.当然,您根本不应该使用
complex*
。 The argument mismatch can be seen using complex(kind=..)
.使用
complex(kind=..)
可以看到参数不匹配。
Consider the following "Fortran" source:考虑以下“Fortran”源:
subroutine s(r, i, c)
real(kind(0d0)) :: r, i
complex(kind(0e0)) :: c
c = cmplx((r*2),(i*2))
end subroutine s
interface ! Interface block required to lie to some versions of gfortran
subroutine s(r, i, c)
real(kind(0d0)) :: r, i
complex(kind(0d0)) :: c
end subroutine s
end interface
complex(kind(0d0)) c
call s(4d0, 10d0, c)
print*, c%re
end
and compare it with the Fortran source:并将其与 Fortran 源进行比较:
subroutine s(r, i, c)
real(kind(0d0)) :: r, i
complex(kind(0d0)) :: c
c = cmplx((r*2),(i*2))
end subroutine s
complex(kind(0d0)) c
call s(4d0, 10d0, c)
print*, c%re
end
Further, rather than using kind(0d0)
etc., there are the various C interoperability constants and storage-size constants of iso_fortran_env
.此外,除了使用
kind(0d0)
等之外,还有各种 C 互操作性常量和iso_fortran_env
的存储大小常量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.