Использование Fortran DLL в VB

Я пытаюсь научить себя вызывать фортран-подпрограмму из VB. И я пытаюсь работать с очень простыми примерами, но почему-то это не работает. Я использую Visual Studio 2010 с Intel Visual Fortran. Вот код, который я пытаюсь:

SUBROUTINE ARRAYTEST(arr)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS:"ARRAYTEST" :: ARRAYTEST
REAL arr(3, 7)
INTEGER i, j
DO i = 1, 3
    DO j = 1, 7
        arr (i, j) = 11.0 * i + j
    END DO
END DO
END SUBROUTINE

И он успешно собирается, чтобы создать файл DLL. А вот мой Visual Basic код:

Public Class Form1
Private Declare Sub ARRAYTEST Lib "FortTest.DLL" Alias "ARRAYTEST" (ByVal x As Single)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim arr(0 To 2, 0 To 6) As Single
    Call ARRAYTEST(arr(0, 0))
    TextBox1.Text = arr(3, 3)
End Sub

End Class

Когда я помещаю файл DLL в каталог и запускаю код, я получаю следующую ошибку: Первое исключение типа "System.AccessViolationException" произошло в ForRun.exe

Я погуглил, но не нашел решения, я был бы очень признателен, если бы кто-то мог сказать мне, что я делаю неправильно и как это исправить. Огромное спасибо заранее.

2 ответа

Вы можете попробовать DllImport нотация, с которой у меня был наибольший успех в этом конкретном сценарии (FORTRAN из VB.NET).

Imports System.Runtime.InteropServices

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim arr(0 To 2, 0 To 6) As Single
        ARRAYTEST(arr(0, 0))
        TextBox1.Text = arr(3, 3)
    End Sub

End Class

Public Module FortranInterop
    <DllImport("FortTest.DLL", CallingConvention:=CallingConvention.StdCall, EntryPoint:="ARRAYTEST")> _
    Public Sub ArrayTest(ByRef x as Single)
    End Sub    
End Module
  1. Первое, что я упомяну, это то, что передаваемые переменные ByReference необходимо при прохождении массивов. Я почти уверен, что мы передаем ВСЕ наши переменные по ссылке, но я не уверен, что это необходимо, если FORTRAN не изменяет его. Это может быть источником вашей ошибки AccessViolation.

  2. Во-вторых, я поставил StdCall CallingConvention, но я не уверен на 100%, какое соглашение о вызовах по умолчанию применяется в IVF. Мы всегда явно устанавливаем это CDECL в заголовке нашего атрибута.

  3. Наконец, я бы с осторожностью передавал 2D(+) массивы на FORTRAN. Я не думаю, что я действительно проверял или видел это, но я читал на форумах разработчиков IVF, что FORTRAN транспонирует массивы, переданные из.NET (строки становятся столбцами). Просто еще одна вещь, о которой нужно знать.

Я знаю, что это старый вопрос, но есть простой ответ, который, кажется, никто не заметил. Вы объявили arr(от 0 до 2, от 0 до 6), но вы вызываете arr(3,3), который находится за пределами вашего объявления (3 не содержится в 0 до 2). System.AccessViolationException - распространенная ошибка, которая обычно указывает на то, что вы ссылались за пределы массива, т.е. вы пытаетесь получить доступ к тому, что в памяти не было зарезервировано для этой переменной, следовательно, нарушение доступа.

Если вы использовали TextBox1.Text = arr(2,3), вы не должны получить эту ошибку, и все должно работать нормально.

Надеюсь, что это поможет любому, кто смотрит на вопрос сейчас.

Другие вопросы по тегам