簡體   English   中英

如何將 Fortran 的復雜類型傳遞給 C#?

[英]How do you pass Fortran's complex type to C#?

假設我有以下 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 代碼編譯用

gfortran -c complex_passing.f90
gfortran -fPIC -shared -o complex_passing.dll complex_passing.o

我如何在 C# 中調用這個子程序? 我嘗試了以下代碼:

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);
    }
}
            

收效甚微 - 我的 COMPLEX 結構似乎正在返回垃圾數據:

Real: 134217760.5
Imaginary: 0

當我期望實部是 8 而虛部是 20 時。

gfortran 將非標准COMPLEX*8視為大小為 8 字節的復數,實部和虛部各 4 字節。 相反,您需要一個 16 字節的復數,實部和虛部各有 8 個字節( COMPLEX*16 ),或者您應該相應地更改 C# 端。

在 gfortran 下可以看到以下效果:

complex*8 :: c8 = (8d0, 20d0)
complex*16 :: c16 = 0

c16%re = TRANSFER(c8,c16)

print*, c8, c16 

end

當然,您根本不應該使用complex* 使用complex(kind=..)可以看到參數不匹配。

考慮以下“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

並將其與 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

此外,除了使用kind(0d0)等之外,還有各種 C 互操作性常量和iso_fortran_env的存儲大小常量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM