gpt4 book ai didi

c# - 从 C# 调用 Fortran DLL

转载 作者:行者123 更新时间:2023-11-30 16:13:24 24 4
gpt4 key购买 nike

我有一个关于从 C#(使用 VS 2010)调用 fortran DLL 的问题。

我无法让这个程序运行。当从 C# 进入 Fortran 代码时,在计算 z 的行(xy 的总和),会弹出一个消息框:

An unhandled exception of type 'System.AccessViolationException' occurred in WinApp_FortranDLLStruct2.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt"

我该如何解决这个问题?

Fortran DLL 称为“TestDLL.DLL”

Fortran 代码:

MODULE TESTING
TYPE Point
REAL*8 :: x(10)
REAL*8 :: y(10)
REAL*8 :: z(10)
ENDTYPE Point
end module

!DEC$ ATTRIBUTES DLLEXPORT::CalcPoint
!DEC$ ATTRIBUTES ALIAS : "CalcPoint" :: CalcPoint

SUBROUTINE CalcPoint(myPts)
use TESTING
IMPLICIT NONE
INTEGER*4 I,J,NPTS
REAL*8 Sum_Out
TYPE(Point) :: myPts

do i = 1,10
myPts.z(i) = myPts.x(i) + myPts.y(i)
enddo

END SUBROUTINE CalcPoint

C#代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WinApp_FortranDLLStruct2 {
public partial class Form1 : Form {
[StructLayout(LayoutKind.Sequential)]
public unsafe struct myPoint {
public fixed double x[10];
public fixed double y[10];
public fixed double z[10];
}
public class FortranCall {
[DllImport("TestDLL.dll")]
public unsafe static extern void CalcPoint([Out] myPoint t);
}

public Form1()
{
InitializeComponent();
}

private unsafe void button1_Click(object sender, EventArgs e) {
int i;
double d1 = 1.0;

myPoint T = new myPoint();
for (i = 0; i < 10; i++) {
T.x[i] = (i+1)*d1;
T.y[i] = (i+2)*d1;
}
FortranCall.CalcPoint(T);
}
}
}

最佳答案

添加 C 调用约定解决了我的堆栈不平衡问题。还要将 [Out] 更改为 ref 以指向同一内存而不是复制值。这是我的代码

语言

MODULE TESTING
INTEGER, PARAMETER :: SIZE = 10
TYPE Point
SEQUENCE
REAL*8 :: x(SIZE), y(SIZE) , z(SIZE)
ENDTYPE Point
end module


SUBROUTINE CalcPoint(myPts)
!DEC$ ATTRIBUTES DLLEXPORT::CalcPoint
!DEC$ ATTRIBUTES ALIAS : 'CalcPoint' :: CalcPoint
use TESTING
IMPLICIT NONE
! Arguments
TYPE(Point), INTENT(INOUT) :: myPts
! Local variables
INTEGER*4 I

do i = 1,SIZE
myPts%z(i) = myPts%x(i) + myPts%y(i)
enddo

END SUBROUTINE CalcPoint

C#

[StructLayout(LayoutKind.Sequential)]
public unsafe struct myPoint
{
public const int size = 10;
public fixed double x[size];
public fixed double y[size];
public fixed double z[size];

public void Initialize(double d1)
{
fixed (double* x_ptr=x, y_ptr=y, z_ptr=z)
{
for (int i=0; i<size; i++)
{
x_ptr[i]=(i+1)*d1;
y_ptr[i]=(i+1)*d1;
z_ptr[i]=0.0;
}
}
}
}

class Program
{
[DllImport(@"FortranDll1.dll", CallingConvention=CallingConvention.Cdecl)]
public unsafe static extern void CalcPoint(ref myPoint t);

unsafe Program()
{
double d1=1.0;
var T=new myPoint();
T.Initialize(d1);
Program.CalcPoint(ref T);
// T.z = {2,4,6,...}
}

static void Main(string[] args)
{
new Program();
}
}

附录

要将固定数组转换为托管数组,反之亦然,请使用以下代码

public unsafe struct myPoint
{
public const int size=10;
public fixed double x[size];
...
public double[] X
{
get
{
double[] res=new double[size];
fixed (double* ptr=x)
{
for (int i=0; i<size; i++)
{
res[i]=ptr[i];
}
}
return res;
}
set
{
if (value.Length>size) throw new IndexOutOfRangeException();
fixed (double* ptr=x)
{
for (int i=0; i<value.Length; i++)
{
ptr[i]=value[i];
}
}
}
}
}

关于c# - 从 C# 调用 Fortran DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21762981/

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