将数组指针从 Fortran(被调用方)传递到 C#(调用方)

本文关键字:调用 数组 指针 Fortran | 更新日期: 2023-09-27 17:56:36

我正在尝试将浮点数组从 C# 传递到 fortran,并让 fortran 将其引用更改为内部(在 fortran 代码中)数组。当我这样做时,我只是得到垃圾,尽管它运行良好。以下是我的工作:

float[] test = new float[50];
testpointer_( test);
[DllImport("ArrayPointerTest.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void testpointer_([Out] float[] array);//Out keyword makes no difference

!DEC$ ATTRIBUTES DLLEXPORT::testpointer
subroutine testpointer(arrayout)
  implicit none
real, dimension(1:50), target :: arrayin
real, dimension(:), pointer :: arrayout
integer :: i

DO i=1,50
    arrayin(i)=i
end do
arrayout => arrayin
end subroutine

为什么?因为我正在将遗留代码制作成 dll,并且不想进行不必要的更改。有什么想法吗?

使用接受的答案和一些更改
进行更新这段代码成功地使 C#:"test" 以 fortran:"arrayin" 的值为目标。

[DllImport("ArrayPointerTest.dll", CallingConvention = CallingConvention.Cdecl)]
        static unsafe extern void testpointer(float* arrayPtr);
  private unsafe static void PointerTest()
        {
            float[] teste = new float[50];
            teste[49] = 100;
            fixed (float* testePtr = teste)
            {
                testpointer(testePtr);
            }
            for (int i = 0; i < 50; i++)
            {
                Console.WriteLine(teste[i]);
            }
            Console.Read();
        }

!DEC$ ATTRIBUTES DLLEXPORT::testpointer
subroutine testpointer(arrayout_) bind(c)
  use iso_c_binding
  implicit none

real(c_float), dimension(1:50), target :: arrayin
type(c_ptr), value ::arrayout_
real(c_float), dimension(:), pointer :: arrayout
integer :: i
call c_f_pointer(arrayout_, arrayout, [50])
do i=1,50
        arrayin(i) = i*2!you can also change arrayout here, it will be reflected
end do
arrayout = arrayin ! todo: is this causing a copy to be made, or is it changing the pointer's references?

end subroutine

将数组指针从 Fortran(被调用方)传递到 C#(调用方)

使用 iso_c_binding

!DEC$ ATTRIBUTES DLLEXPORT::testpointer
subroutine testpointer(arrayout) bind(c)
  use iso_c_binding
  implicit none
real(c_float), dimension(1:50), target :: arrayin
real(c_float), dimension(:), pointer :: arrayout
integer :: i

DO i=1,50
    arrayin(i)=i
end do
arrayout => arrayin
end subroutine

使用bind(c),您也不需要修改过程名称:

static extern void testpointer([Out] float[] array);//Out keyword makes no difference

您还必须小心传递数组。我会使用c_ptr

!DEC$ ATTRIBUTES DLLEXPORT::testpointer
subroutine testpointer(arrayout_) bind(c)
  use iso_c_binding
  implicit none
type(c_ptr),value::arrayout_
real(c_float), dimension(:), pointer :: arrayout
call c_f_pointer(arrayout_, arrayout, [50])