Использование 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
Первое, что я упомяну, это то, что передаваемые переменные
ByReference
необходимо при прохождении массивов. Я почти уверен, что мы передаем ВСЕ наши переменные по ссылке, но я не уверен, что это необходимо, если FORTRAN не изменяет его. Это может быть источником вашей ошибки AccessViolation.Во-вторых, я поставил StdCall CallingConvention, но я не уверен на 100%, какое соглашение о вызовах по умолчанию применяется в IVF. Мы всегда явно устанавливаем это
CDECL
в заголовке нашего атрибута.Наконец, я бы с осторожностью передавал 2D(+) массивы на FORTRAN. Я не думаю, что я действительно проверял или видел это, но я читал на форумах разработчиков IVF, что FORTRAN транспонирует массивы, переданные из.NET (строки становятся столбцами). Просто еще одна вещь, о которой нужно знать.
Я знаю, что это старый вопрос, но есть простой ответ, который, кажется, никто не заметил. Вы объявили arr(от 0 до 2, от 0 до 6), но вы вызываете arr(3,3), который находится за пределами вашего объявления (3 не содержится в 0 до 2). System.AccessViolationException - распространенная ошибка, которая обычно указывает на то, что вы ссылались за пределы массива, т.е. вы пытаетесь получить доступ к тому, что в памяти не было зарезервировано для этой переменной, следовательно, нарушение доступа.
Если вы использовали TextBox1.Text = arr(2,3), вы не должны получить эту ошибку, и все должно работать нормально.
Надеюсь, что это поможет любому, кто смотрит на вопрос сейчас.