Проблема с расположением файла в Excel / Fortran DLL-соединения - PullRequest
1 голос
/ 09 июня 2009

Платформа: WinXP SP2, Intel Fortran 11, Excel 2007

У меня проблемы с подключением DLL-файла с Excel.

Файл dll относительно прост:

subroutine FortranCall (r1, num)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE, ALIAS:"FortranCall" :: FortranCall
integer, intent(in) :: r1
character(10), intent(out) :: num
!DEC$ ATTRIBUTES REFERENCE :: num

num = ''
write (num,'(i0)') r1 * 2

return
end subroutine FortranCall

сборка с: ifort / nologo / dll Fcall.f90 , и после этого копируется в каталог «temp» на диске C ( как в любом случае написать обратную косую черту здесь (кроме / Вставить)? )

и у меня есть файл Excel с листом 1:

Private Sub CommandButton1_Click()
Dim r1 As Long
Dim num As String * 10

     r1 = 123
     Call FortranCall(r1, num)

     TextBox1.Text = "Answer is " & num

End Sub

и в Moduel1:

Declare Sub FortranCall Lib "C:\temp\Fcall.dll" (r1 As Long, ByVal num As String)

При запуске выдает ошибку: ошибка выполнения 53, файл не найден c: \ temp \ fcall.dll

Кто-нибудь знает, что может быть не так?

Ответы [ 6 ]

2 голосов
/ 18 февраля 2012

Я знаю, что это очень старый вопрос, но я столкнулся с этим вопросом на днях и подумал, что выложу ответ для потомков. Мой VBA-код, вызывающий Fortran DLL, отлично работал на моем компьютере, но не на компьютере моего босса или кого-либо еще. В итоге проблема заключалась в зависимости от других библиотек DLL, несмотря на то, что компиляция выполнялась в режиме «release» вместо «debug». Я использовал Dependency Walker , чтобы проверить зависимости в DLL на компьютере, где он не будет работать, нашел две DLL, которые поставляются с нужным компилятором Intel, и распространил их с моей собственной скомпилированной DLL. 1003 *

1 голос
/ 17 декабря 2010

У меня была такая же проблема - супер расстраивает!

У меня была похожая декларация в Excel VBA: Объявите Sub FortranCall Lib "C: \ temp \ Fcall.dll" (r1 Пока, ByVal num As String)

Он работал на моем компьютере, но не работал на компьютере моего босса. Все написание имени файла и спецификации пути были в порядке. Моя DLL была скомпилирована в Microsoft Visual C ++ 6.0. Проблема заключалась в том, что «Файл не найден / Ошибка выполнения 53» является причиной того, что вызывающее приложение не может найти библиотеки DLL, от которых на самом деле зависит соответствующая библиотека DLL !!! Я дал своему боссу библиотеку DLL, скомпилированную в режиме отладки - в этом случае DLL использует множество других отладочных версий DLL, которые обычно не встречаются на обычных компьютерах. Когда я дал моей босс РЕЛИЗ версии DLL, она работала нормально! Смотрите также: http://software.intel.com/en-us/forums/showthread.php?t=42472

1 голос
/ 10 июня 2009

Вы можете попробовать переместить вашу DLL в C: \ Windows \ system32 (или любую другую папку, которая находится по пути по умолчанию) и изменить часть Lib на "FCall.dll". Это должно устранить любые странности с поиском фактического файла

1 голос
/ 10 июня 2009

Не уверен, что может быть не так.

Мне не удалось заполучить компилятор ifort, но я попробовал ваш код, скопировав произвольную DLL-библиотеку в папку Temp, указав оператор Declare. Когда я запускаю его, я получаю сообщение об ошибке: «Не удается найти точку входа DLL FortranCall в C: \ Temp \ RandomDLL.DLL», что согласуется с использованием неправильной библиотеки DLL (то есть библиотека DLL была найдена, но не соединяется с вызывающим кодом).

Вы можете попытаться заменить скомпилированную вами DLL случайной другой DLL и посмотреть, не возникнет ли та же ошибка. Если да, то это проблема среды ОС, а не компилятора.

Это, вероятно, не очень полезно, но может исключить одну или две возможности.

Среда, которую я использовал: Win Vista, Excel 2003

0 голосов
/ 17 сентября 2017

Ну, это может быть слишком поздно, но нужно рассмотреть ряд вопросов

1) «Соглашение о вызовах» должно соответствовать правильно. Это имеет несколько различных аспектов, некоторые из которых:

a) Прописная или нет или комбинация имен s / r и Arg.

б) Srting соглашения о вызовах. В своем коде вы использовали некоторое «сочетание» вещей и, кажется, упускаете некоторые биты.

Например, попробуйте это

subroutine FORTRANCALL (R1, NUM)        ! notice capitalisation
!DEC$ ATTRIBUTES DLLEXPORT :: FORTRANCALL   ! notice capitalisation  and default "calling convention" (this varies between compilers)
                    ! but older CVF and Intel compilers default to CDECL, which you can set in your "properties" etc.  
                    ! Its been a while but I think newer IVF have changed to a different default convention
                    ! e.g. if you were doing this, say, in GCC/gFortran, there would be a much longer discussion
integer, intent(in) :: r1
Character(Len=10), intent(out) :: num   ! you might be able to use Character(Len=*) so long as its fixed on the VBA side
!   remove this => !DEC$ ATTRIBUTES REFERENCE :: num

num = ''
write (num,'(i0)') r1 * 2

return
end subroutine FortranCall

На стороне VBA объявление:

Declare Sub FortranCall_XX Lib "C:\ ... your path ...\Fcall.dll.dll" _
Alias "FORTRANCALL" (R1 as Long, ByVal NUM As String, ByVal NumLen as Long)

ОБРАТИТЕ ВНИМАНИЕ, дополнительный Arg для строки String, это появляется только на стороне VBA, и ТОЛЬКО, когда String передается ByVal (любая другая передача строки и особенно массивы строк - гигантская проблема ... выполнима, но будьте готовы к немного домашней работы).

Кроме того, строка len здесь просто следует за строкой с точки зрения позиции Arg. Однако, если num был расположен ранее, местоположение NumLen будет либо просто следовать за Arg num, либо в конце списка Arg, в зависимости от соглашения о вызовах.

Кроме того, когда вы создаете DLL, компилятор также часто создает файл «Def». Вам не нужно напрямую обращаться к файлу Def при использовании VBA / Fortran. Однако, заглянув внутрь, вы увидите точный «стиль именования» того, что, по мнению компилятора, должен называться ваш s / r. Например, при некоторых соглашениях о вызовах файл Def может показывать имя вашего s / r как-то так: __fortrancall @ 12

... что бы ни говорили файлы Def, это то, что вы должны использовать в объявлении VBA Alias ​​"__fortrancall @ 12"

... эти вещи требуют длительного обсуждения для общей реализации с различными соглашениями о вызовах / компиляторами.

Кстати: я добавил «_XX» исключительно для того, чтобы фактическая UDF VBA имела «очевидное имя», скажем FortranCall, или что-то еще ... разумная привычка, если вы будете делать это много, особенно с Функции и т. Д., Но не слишком важные здесь.

и саб VBA становится:

Private Sub CommandButton1_Click()
Dim r1 As Long
Dim num As String * 10
Dim numlen as Long

 numlen = 10                ' required string len, can automate via intrinsics etc

 r1 = 123
 Call FortranCall_XX(r1, num, numlen)   ' notice the extra Arg

 TextBox1.Text = "Answer is " & num     ' you may wish to add Trim() or something in case returned num does not require 10 chars

End Sub

2) Вам действительно нужно передать num в виде строки? Передача строк между VBA и DLL - это большая банка червей. Почему бы не передать num как Double или что-то еще?

Если это должна быть строка и если это ByVal, то вы также должны включить длину строки как ByVal Long на стороне VBA (поскольку в Fortran строка len является скрытым значением), как показано выше.

Вы можете пройти мимо Ref и с / без дополнительного StringLen, если вы знаете, как использовать (Cray) указатели или варианты на стороне Fortran для преобразования VBString в строку Fortran и т. Д. ... длинное долгое обсуждение.

3) Более общий и "определенный" способ распространения / подключения к dll - это преобразование листа / модуля XL в XLA ... т.е. в надстройку. Затем XLA и DLL (обычно) помещаются в один и тот же Dir, и надстройка добавляется в Excel с помощью инструментов / надстроек и т. Д., Которая позволяет просматривать правильный путь.

Затем вы также можете вызывать своих з / р из любой рабочей книги / листа и т. Д., А не только из одной рабочей книги.

0 голосов
/ 02 июля 2014

Недавно у меня было то же самое с ifort 14, и проблема исчезает, когда я компилирую с

ifort /dll /libs:static /threads

Вместо

ifort /dll

Сообщение "файл не найден" часто возникает, когда DLL зависит от другой DLL, которая не находится по системному пути (у меня это было с gfortran и DLL, например, в MinGW32 \ bin ). Но я не нашел такой зависимости здесь, довольно странно.

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