gpt4 book ai didi

c# - 键入编码以从 C# 调用 fortran 子例程

转载 作者:太空宇宙 更新时间:2023-11-03 11:33:40 24 4
gpt4 key购买 nike

我正在尝试使用 P/invoke 从 C# 代码调用 FORTRAN77 子例程 - 如果您有兴趣,我正在尝试封装 ARPACK 库 (http://www.caam.rice.edu/software/ARPACK) 提供的一些功能。我有 2 个问题。


首先,我无法在任何地方找到有关此上下文中类型编码的明确说明。更具体地说,这是在我的 FORTRAN 子例程中声明的类型:

       subroutine getEigenVectors
& ( Matrix, n, which, nev, ncv, maxn, maxnev, maxncv, ldv, v, d)

c %------------------%
c | Scalar Arguments |
c %------------------%

character which*2
integer n, nev, maxn, maxnev, maxncv, ldv

c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& Matrix(n,n), v(ldv,maxncv), d(maxncv,2)

我在这里找到了一些有值(value)的信息: What Should I MarshalAs for Character Type in Fortran? ,我从中暗示(我可能是错的)我应该使用:

  • [MarshalAs(UnmanagedType.I4)] int 传入整数
  • [MarshalAs(UnmanagedType.LPArray)] byte[] 传入字符串

但是,我完全不知道如何处理 Real 数组。 有人对此有任何想法吗?


其次,我对是否应该将我的论点作为引用传递感到困惑。我对 FORTRAN 一点也不熟悉——我知道,这让任务有点困难;然而,只有 ARPACK 做我想做的事。我确实在某处读到过 FORTRAN 子例程默认将所有参数作为引用。 因此我应该将所有参数作为引用传递吗?

在此先感谢您的帮助!纪尧姆


编辑 (8/6/11)

所以这是我的最终看法:

    [DllImport("Arpack.dll", EntryPoint = "#140")]
private static extern void getEigenVectors(
[MarshalAs(UnmanagedType.LPArray)] ref float[,] matrix,
[MarshalAs(UnmanagedType.I4)] ref int n,
[MarshalAs(UnmanagedType.LPArray)] ref byte[] which,
[MarshalAs(UnmanagedType.I4)] int whichLength,
[MarshalAs(UnmanagedType.I4)] ref int nev,
[MarshalAs(UnmanagedType.I4)] ref int ncv,
[MarshalAs(UnmanagedType.I4)] ref int maxn,
[MarshalAs(UnmanagedType.I4)] ref int maxnev,
[MarshalAs(UnmanagedType.I4)] ref int maxncv,
[MarshalAs(UnmanagedType.I4)] ref int ldv,
[MarshalAs(UnmanagedType.LPArray)] ref float[,] v,
[MarshalAs(UnmanagedType.LPArray)] ref float[,] d
);

我在这里做了几件事:

  • 传递 int 对象作为 UnmanagedType.I4 匹配 FORTRAN integer 对象
  • 传递大小为 (m, n) 的 float[,] 对象并编码为 UnmanagedType.LPArray 以匹配 FORTRAN Real(n,m)对象
  • 将获得的 byte[] 对象传递为 UnmanagedType.LPArray 以匹配 FORTRAN Character*n 对象。 byte[] 对象计算如下:

    System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
    byte[] which = encoding.GetBytes(myString);
  • 按值传递 int 对象并将其编码为 UnmanagedType.I4 以指示字符串的长度。请注意,我试图将该参数放在字符串之后以及参数列表的末尾。

这是我最好的镜头 - 无论是这个还是我尝试过的所有其他东西都没有奏效。该方法将执行,但是它退出的速度非常快(当它应该进行一些非常严格的计算时)。而且,我的3个数组变成了奇怪的一维数组。这是调试器给我的:

enter image description here

有什么想法吗?

最佳答案

我建议您从一些小的测试代码开始。用一些带有简单参数的子例程编译 FORTRAN .dll,然后使用 C# 来使调用工作。此外,您可能希望将带有许多参数的 Fortran 封装到一个结构中(TYPE 关键字),这使得互操作变得更加容易。

这是一个工作示例,您可以使用它来了解它的工作原理。

原始 FORTRAN 代码:

  SUBROUTINE CALC2(BLKL,BLKW, N_LAMINA,N_SLICE, LOAD, SLOP,SKW,    &
DIA1,DIA2, Y1, Y2, N1, N2, DROP1, DROP2, &
PARRAY, P_MAX, P_MAX_INDEX, ENDEFCT)
!DEC$ ATTRIBUTES DLLEXPORT :: CALC2
!DEC$ ATTRIBUTES ALIAS:'CALC2' :: CALC2
!DEC$ ATTRIBUTES VALUE :: BLKL, BLKW, N_LAMINA, N_SLICE, LOAD, SLOP, SKW
!DEC$ ATTRIBUTES VALUE :: DIA1, DIA2, Y1, Y2, N1, N2
IMPLICIT NONE
INTEGER*4, INTENT(IN) ::N_LAMINA, N_SLICE
REAL*4, INTENT(IN) :: BLKL, BLKW, LOAD, SLOP, SKW, &
DIA1, DIA2, Y1, Y2, N1, N2, &
DROP1(MAX_LAMINA), DROP2(MAX_LAMINA)
REAL*4, INTENT(OUT):: PARRAY(MAX_PATCH), P_MAX
INTEGER*4, INTENT(OUT) :: P_MAX_INDEX, ENDEFCT
INTEGER*4 :: NDIAG, N_PATCH
REAL*4 :: SLNG, SWID
REAL*4 :: DROPS_1(MAX_LAMINA), DROPS_2(MAX_LAMINA)

...

END SUBROUTINE CALC2

具有实数和整数形式的各种标量和数组值。例如 DROP1 是输入的一维数组。 PARRAY 将二维数组输出为一维数组。 BLKL 是输入 float 。

注意 !DEC$ ATTRIBUTES VALUE 装饰以避免将所有内容声明为 ref

C# 中,代码由

调用
    [DllImport("mathlib.dll")]
static extern void CALC2(float major_dim, float minor_dim,
int N_lamina, int N_slices, float total_load,
float slope, float skew, float diameter_1, float diameter_2,
float youngs_1, float youngs_2, float nu_1, float nu_2,
float[] drops_1, float[] drops_2, float[] pressures,
ref float p_max, ref int p_max_index, ref EndEffect end_effect);

...
{
float max_pressure = 0;
int max_pressure_index = 0;
float[] pressures = new float[Definition.MAX_PATCH];
EndEffect end_effect = EndEffect.NO;

CALC2(length, width, lamina_count, slice_count, load, slope, skew,
dia_1, dia_2, y_1, y_2, n_1, n_2, drops_1, drops_2, pressures,
ref max_pressure, ref max_pressure_index, ref end_effect);
}

注意我没有传递任何字符串。

关于c# - 键入编码以从 C# 调用 fortran 子例程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6961410/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com