AccessViolationException не было обработано, вызывая Fortran DLL из VB Net - PullRequest
0 голосов
/ 27 мая 2010

У меня есть подпрограмма, написанная на фортране, которую мне нужно вызвать из VB.NET, где написаны все остальные мои функции. Я не писал фортран, и вряд ли знаю фортран. Я получаю ниже исключение на мой вызов функции DLL и не знаю, как это исправить. Интересно, связано ли это с неконгруэнтной переменной длиной?

У меня есть источник для моего фортрана, и я скомпилировал его с помощью компилятора g95. Я попытался скомпилировать его с флагом, на котором все реалы должны быть установлены в 32 бита (-r4). Меня убеждает, что вам не нужно инициализировать переменные перед использованием в Фортране. Я думал, что это должен быть язык с ребрами.

В любом случае, вот исключение, которое я получаю:

System.AccessViolationException было необработанное сообщение = попытка чтения или запишите защищенную память. Это часто указание на то, что другая память поврежден. Источник = PTPWrapper
Трассировки стека: в PTPWrapper.Module1.pointtopoint (одиночный & IELEVAT, Single & IDIST, Single & FREQ, Single & HTAMSL, Single & DLOSS, Одноместный & Беспорядок) в PTPWrapper.Module1.Main () в C: \ Documents and Settings \ SGoldman \ my документы \ визуальная студия 2010 \ Projects \ PTPWrapper \ PTPWrapper \ Module1.vb: линия 18 в System.AppDomain._nExecuteAssembly (RuntimeAssembly сборка, строка [] args) в System.AppDomain.ExecuteAssembly (String AssemblyFile, Доказательства AssemblySecurity, String [] args) в Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly () в System.Threading.ThreadHelper.ThreadStart_Context (Object государство) в System.Threading.ExecutionContext.Run (ExecutionContext executeContext, ContextCallback обратный вызов, состояние объекта, логическое значение ignoreSyncCtx) в System.Threading.ExecutionContext.Run (ExecutionContext executeContext, ContextCallback обратный вызов, состояние объекта) в System.Threading.ThreadHelper.ThreadStart () InnerException:

вот мое объявление функции VB и вызов функции:

Declare Sub pointtopoint Lib "diff5z11.dll" (ByRef IELEVAT As Single, ByRef IDIST As Single, ByRef FREQ As Single, ByRef HTAMSL As Single, ByRef DLOSS As Single, ByRef CLUTTER As Single)

pointtopoint(elevation(0), distance, freq, height, dlo, clut)

здесь все переменные определены как 32-битные синглы в VB.

и вот первые несколько строк кода фортрана:

subroutine pointtopoint(IELEVAT, IDIST, FREQ, HTAMSL, DLOSS, CLUTTER)

      real ielevat(*)
      dimension oblim(2)

      dd     = 0.1
      EK     = 1.333            !  Earth curvature (4/3 earth)
      HR     = 9.1              !  Rcvr Ant ht (m), for 30 feet 
      HRAMSL = IELEVAT(IDIST) + HR  
      DIST   = float(idist)*dd
      FRESMIN = HR + 1.0
      DLOSS  = 0.0
      TDLOSS = 0.0
      RDLOSS = 0.0
      ADJ    = 0.0

есть идеи, как я могу получить вызов на работу и вернуть свои данные? Спасибо!

Ответы [ 2 ]

1 голос
/ 27 мая 2010

Похоже, вы почти у цели.

Во-первых, я хочу отметить, что вы можете форсировать требуемые объявления на Фортране, и это приветствуется. Для этого добавьте IMPLICIT NONE после объявления подпрограммы:

subroutine pointtopoint(IELEVAT, IDIST, FREQ, HTAMSL, DLOSS, CLUTTER)
    IMPLICIT NONE
    [variable declarations]
    ...
end subroutine pointtopoint

Это может быть хорошей идеей в вашем случае, потому что похоже, что есть некоторая путаница с типом переменной. Если IMPLICIT NONE не используется, компилятор Fortran делает предположения относительно того, что тип переменной по первому символу имени переменной. Любая переменная, которая начинается с I, J, K, L, M или N, считается INTEGER, а все остальное принимается за REAL. Итак, первая проблема, которую я вижу, это IDIST - вы отправляете Single из VB, и это, вероятно, вызывает нарушение доступа к памяти, которое вы видите. Независимо от того, какой номер отправляется как Single, он интерпретируется как INTEGER и, скорее всего, выходит за пределы массива IELEVAT.

Кроме того, еще одна вещь, которую я заметил (и это может не быть ошибкой - я не могу сказать, потому что вся подпрограмма, кажется, не опубликована) - это то, что подпрограмма получает переменную HTAMSL, а затем использует HRAMSL. Это похоже на возможную опечатку, когда программист действительно хотел использовать HTAMSL. HTAMSL и HRAMSL - две совершенно разные переменные. Это еще один побочный эффект неиспользования IMPLICIT NONE - опечатки остаются незамеченными, и вы получите неожиданные результаты.

0 голосов
/ 27 мая 2010

Re "Мне кажется, что вам не нужно инициализировать переменные перед использованием в Фортране."- вам необходимо в Фортране инициализировать переменные перед их использованием.Инициализация и декларирование разные.Старый ФОРТРАН часто использовал «неявную типизацию», при которой переменные неявно печатались по первой букве их имени.Современная практика заключается в явном вводе каждой переменной, но разрешено унаследованному коду компилировать старый метод.Как уже ответил @brady, вы можете заставить компилятор требовать явного объявления каждой переменной, включая «неявное нет».Большинство компиляторов также имеют опцию компилятора для того же эффекта.

Как писал @brady, из неявной типизации IDIST является целым числом и используется в качестве индекса массива.IELEVAT должен быть достаточно большим для значения IDIST, которое вы передаете.Если этого недостаточно, чтобы заставить его работать, вы можете получить больше контроля над вызовами, используя привязку ISO C в Fortran 2003, которая широко доступна в компиляторах Fortran 95.Это скажет Fortran использовать соглашения о вызовах C для подпрограммы, которые с большей вероятностью будут соответствовать ожиданиям VB.И вы можете контролировать, передается ли аргумент по значению или по ссылке.

Что-то вроде:

subroutine pointtopoint (IELEVAT, IDIST, FREQ, HTAMSL, DLOSS, CLUTTER) bind (C, name="pointtopoint")

implicit none   ! optional
real (c_float), dimension (*) :: IELEVAT
integer (c_int) :: IDIST
real (c_float) :: FREQ, HTAMSL, DLOSS, CLUTTER

В руководстве gfortran есть некоторая документация: http://gcc.gnu.org/onlinedocs/gfortran/Mixed_002dLanguage-Programming.html Для MS Windows:вам может потребоваться расширение для выбора между соглашениями о вызовах: http://gcc.gnu.org/onlinedocs/gfortran/GNU-Fortran-Compiler-Directives.html#GNU-Fortran-Compiler-Directives

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...