2017-03-12 10 views
1

VB呼び出しFortranの簡単な例を試してみると、どのアプローチを取ろうとしているかによって2つのエラーが発生しています。下記の小さな再現可能な例は簡単ですが、はるかに大きな問題の前駆体です。VB.NETのFortran呼び出し:PInvoke例外を修正する方法は?

この簡単な例の主な目的は、Fortranコード(この場合は「SUMMATION」)に渡される引数の値を調整し、VBで返された(調整済みの)値を使用することです。私が最初にエラーメッセージと共に各アプローチの結果を、それを呼び出すために使用VBコードの2つのバリエーションを示し、その後、単純なFortranコードを提供

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 

がエラーを与える:

enter image description here

私がしようとすると「ワイヤーアップ」少し異なる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 

は、次の例外を提供します:

enter image description here

この第二のアプローチは動作します - 私は誤りを認めた場合、私は移動することができることを意味し過去の問題を解決する方法を教えてください。私が取り組もうとしているより大きな問題は、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例外に終わりました。最初に、この例外が大きな問題であるかどうかを疑問に思っています(つまり、この例外がスローされたときに、コードを移動して暖かいことを意味する)。もしそれが修正されるべきであるなら(私はこれが事実であると仮定します)、あなたは私の問題が何であるかを見て、助けてください。

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)

+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 Sub...

Public Function...を持っていた: –

+0

Fortranサブルーチンを 'INTEGER、Intent(in)、value :: KPER、KSTP'に変更すると、改善されますか? – francescalus

+0

値は 'bind(C)'を伴います。 –

答えて

0

は、使用して解決策を見つけましたコンパイラを使用します。私は95%がCallingConventionが間違っていると確信しています、Cdeclでなければなりません。 FunctionではなくSubが引数ByRefを渡しました。
関連する問題