在编写VB调用fortran的简单示例时,我会根据我尝试采用的方法获得两个错误。虽然下面的小型可重复示例很简单,但它是更大问题的前兆。
这个简单示例的主要目标是调整传递给Fortran代码的参数的值(在本例中为" SUMMATION"),然后使用VB中返回的(和调整的)值。
我首先提供简单的fortran代码,然后显示用于调用它的VB代码的两种变体以及每种方法产生的错误消息。
VB调用的Fortran代码:
SUBROUTINE MFNWT_RUN(KSTP,KPER,SUMMATION)
!DEC$ ATTRIBUTES DLLEXPORT :: MFNWT_RUN
!DEC$ ATTRIBUTES ALIAS: "MFNWT_RUN" :: MFNWT_RUN
IMPLICIT NONE
INTEGER, Intent(in) :: KPER, KSTP
INTEGER, Intent(inout) :: SUMMATION
INTEGER kkper, kkstp
INTEGER add_em_up
kkper = KPER
kkstp = KSTP
add_em_up = kkper + kkstp
SUMMATION = add_em_up
END SUBROUTINE
调用VB代码(第一种方法):
Imports System.Collections
Imports System
Imports System.Runtime.InteropServices
Imports System.IO
Imports System.Data
Module Module1
<DllImport("example_fortran_directory.dll", CallingConvention:=CallingConvention.StdCall)>
Public Function MFNWT_RUN(ByVal a As Integer, ByVal b As Integer, ByRef Divs As Integer) 'ref bool AdvFlwRdr
End Function
' Private Declare Sub MFNWT_RUN Lib "example_fortran_directory.dll" Alias "MFNWT_RUN" (<[In](), Out()> ByRef A As Integer, ByRef B As Integer, ByRef C As Integer)
'Declare Sub MFNWT_RUN Lib "example_fortran_directory" (ByRef A As Integer, ByRef B As Integer, ByRef C As Integer)
Sub Main()
Dim first As Integer
Dim second As Integer
Dim answer As Integer
first = 6
second = 7
answer = 0
Call MFNWT_RUN(first, second, answer)
MsgBox(answer)
End Sub
End Module
给出错误:
如果相反,我会尝试“&#39;连线”&#39;对Fortran DLL的调用有点不同(注释掉DllImport代码并取消注释声明代码),我得到了一个不同的错误。
调用VB代码(第二种方法):
Imports System.Collections
Imports System
Imports System.Runtime.InteropServices
Imports System.IO
Imports System.Data
Module Module1
' Private Declare Sub MFNWT_RUN Lib "example_fortran_directory.dll" Alias "MFNWT_RUN" (<[In](), Out()> ByRef A As Integer, ByRef B As Integer, ByRef C As Integer)
Declare Sub MFNWT_RUN Lib "example_fortran_directory" (ByRef A As Integer, ByRef B As Integer, ByRef C As Integer)
Sub Main()
Dim first As Integer
Dim second As Integer
Dim answer As Integer
first = 6
second = 7
answer = 0
Call MFNWT_RUN(first, second, answer)
MsgBox(answer)
End Sub
End Module
给出以下例外:
第二种方法有效 - 这意味着如果我承认错误我可以通过它,但如果有人可以指示我如何操作,我宁愿修复潜在的问题?我想要解决的更大问题是从VB进行数千次对Fortran的调用,因此以正确的方式修复堆栈不平衡错误似乎是至关重要的(而不仅仅是关闭警告消息)。
追加另一个也导致PInvokeStackImbalance错误的尝试。
首先是fortran:
SUBROUTINE MFNWT_RUN(KSTP,KPER,SUMMATION)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS: 'MFNWT_RUN' :: MFNWT_RUN
!DEC$ ATTRIBUTES REFERENCE :: KSTP
!DEC$ ATTRIBUTES REFERENCE :: KPER
!DEC$ ATTRIBUTES REFERENCE :: SUMMATION
IMPLICIT NONE
INTEGER, value :: KPER, KSTP
INTEGER, value :: SUMMATION
INTEGER kkper, kkstp
INTEGER add_em_up
kkper = KPER
kkstp = KSTP
add_em_up = kkper + kkstp
SUMMATION = add_em_up
END SUBROUTINE MFNWT_RUN
调用VB:
Imports System.Collections
Imports System
Imports System.Runtime.InteropServices
Imports System.IO
Imports System.Data
Module Module1
Private Declare Sub MFNWT_RUN Lib "example_fortran_directory.dll" Alias "MFNWT_RUN" (<[In](), Out()> ByRef A As Integer, ByRef B As Integer, ByRef C As Integer)
Sub Main()
Dim first As Integer
Dim second As Integer
Dim answer As Integer
first = 6
second = 7
answer = 0
Call MFNWT_RUN(first, second, answer)
MsgBox(answer)
End Sub
End Module
此方法也在抛出PInvokeStackImbalance异常时结束。首先,我想知道这个异常是否是一个大问题(也就是说,我应该简单地取消选中它 - 这意味着代码应该继续运行而不会在抛出此异常时对我产生热情)?如果它是应该修复的东西(我会认为是这种情况),你看到我的问题是什么,请帮助。
答案 0 :(得分:0)
使用以下方法找到解决方案:
<DllImport("example_fortran_directory.dll", CallingConvention:=CallingConvention.Cdecl)>
Public Sub MFNWT_RUN(ByRef a As Integer, ByRef b As Integer, ByRef c As Integer)
End Sub
以前我有Public Function...
而不是Public Sub...
我从来没有能够采用其他方法:
Private Declare Sub MFNWT_RUN Lib "example_fortran_directory.dll" Alias "MFNWT_RUN" (<[In](), Out()> ByRef A As Integer, ByRef B As Integer, ByRef C As Integer)