我有一个C#(NET6)项目,在该项目中我try 调用Fortran子 routine 并传递一个struct
.
我在这里做了简化版本:
克:
using System.Runtime.InteropServices;
Console.WriteLine("C# starting");
Console.WriteLine($"Size of GrandParent: {Marshal.SizeOf(typeof(GrandParent))}");
var gp = new GrandParent();
Natives.SizeCheck(gp);
public static class Natives
{
public const int MaxSize = 100;
[DllImport(dllName: "FortranLib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void SizeCheck(GrandParent gp);
}
[StructLayout(LayoutKind.Sequential)]
public struct Child
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Natives.MaxSize)]
internal double[] Array;
public Child()
{
Array = new double[Natives.MaxSize];
}
}
[StructLayout(LayoutKind.Sequential)]
public struct Parent
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Natives.MaxSize)]
internal Child[] Children;
public Parent()
{
Children = new Child[Natives.MaxSize];
}
}
[StructLayout(LayoutKind.Sequential)]
public struct GrandParent
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Natives.MaxSize)]
internal Parent[] Children;
public GrandParent()
{
Children = new Parent[Natives.MaxSize];
}
}
和FortranLib.dll代码:
module FortranLib
use ISO_C_BINDING
implicit none
integer,parameter :: MaxSize = 100
type, bind(C) :: Child
real(C_DOUBLE) :: Array(MaxSize)
end type Child
type, bind(C) :: Parent
type(Child) :: Children(MaxSize)
end type Parent
type, bind(C) :: GrandParent
type(Parent) :: Children(MaxSize)
end type GrandParent
contains
subroutine SizeCheck(gp)
!DEC$ ATTRIBUTES DLLEXPORT::SizeCheck
!DEC$ ATTRIBUTES DECORATE,ALIAS:"SizeCheck" :: SizeCheck
! Variables
type(GrandParent), intent(in) :: gp
! Body of SizeCheck
write(*,*) "In fortran dll first line"
write(*,*) "Number of parents: ", size(gp%Children)
write(*,*) "Number of children for each parent : ", size(gp%Children(0)%Children)
write(*,*) "Size of child array : ", size(gp%Children(0)%Children(0)%Array)
end subroutine SizeCheck
end module FortranLib
使用MaxSize = 45
行,而不是46行.从46开始,我会遇到"Stack Overflow"异常/崩溃.45岁时,祖父母的年龄是729000岁.
我曾try 在Visual Studio2022的Fortran项目属性下,将配置属性-&>优化-&>堆数组设置为0(表示始终在堆上分配数组)以及配置属性-&>链接器-&>系统-&>堆栈保留大小=MaxSize = 45
000000,我认为这已经足够了,但无济于事.
我开始认为它应该在c#项目中完成,但我不知道在哪里. 有谁知道可以做些什么吗?
EDIT 2022-09-09:
After adding `ref` to the `SizeCheck` parameter in c# it now works up to `MaxSize = 57` but larger values still crash with "Stack overflow".
在(首次)try 反汇编窗口之后
我发现错误在倒数第二行抛出,如下所示(00007FF8CB397F98 E8 73 FC FF FF call CLRStub[MethodDescPrestub]@7ff8cb397c10 (07FF8CB397C10h)
):
5: var gp = new GrandParent();
00007FF8CB397F8B 48 8D 4D 78 lea rcx,[rbp+78h]
00007FF8CB397F8F E8 BC F4 FF FF call Method stub for: GrandParent..ctor() (07FF8CB397450h)
6: Natives.SizeCheck(ref gp);
00007FF8CB397F94 48 8D 4D 78 lea rcx,[rbp+78h]
00007FF8CB397F98 E8 73 FC FF FF call CLRStub[MethodDescPrestub]@7ff8cb397c10 (07FF8CB397C10h)
00007FF8CB397F9D 90 nop
谈到拆卸,我是个新手,但也许这给了别人一个提示……