在excel / fortran dll连接中文件位置的问题

平台:WinXP SP2,英特尔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 / dllbuild立Fcall.f90 ,然后拷贝到C盘的“temp”目录下(这里怎么写一个反斜杠,除了复制/粘贴)?

我有一个Excel文件,在Sheet1中:

 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

任何人有任何线索可能是错误的?

我知道这是一个非常古老的问题,但是前些天我遇到了这个问题,并认为我会为后代作出回答。 我的VBA代码调用Fortran DLL在我的电脑上工作正常,但在我的老板或其他任何人的电脑上都没有问题。 该问题最终依赖于其他DLL,尽管编译在“释放”模式,而不是“调试”。 我使用Dependency Walker来检查DLL中的依赖关系,它不会工作,找到两个与intel编译器一起使用的DLL,并使用我自己编译的DLL分发这些DLL。

不知道什么可能是错的。

我无法使用ifort编译器,但是我通过将一个随机DLL复制到指定了Declare语句的Temp文件夹来尝试执行代码。 当我运行它时,我得到的错误是:“无法找到C:\ Temp \ RandomDLL.DLL中的DLL入口点FortranCall”,这是与使用错误的DLL一致(即,找到该DLL,但它不与调用代码一起)。

您可以尝试用随机的其他DLL替换您编译的DLL,并查看是否得到相同的错误。 如果这样做,这是OS环境的问题,而不是编译器。

这可能不是很有帮助,但可能会消除一两个可能性。

我使用的环境:Win Vista,Excel 2003

您可以尝试将您的DLL移动到C:\ Windows \ system32(或其他位于默认路径上的文件夹),并将Lib部分更改为"FCall.dll" 。 这应该消除定位实际文件的任何古怪

我有同样的问题 – 超级沮丧!

我在Excel VBA中有类似的声明:Declare Sub FortranCall Lib“C:\ temp \ Fcall.dll”(r1 As Long,ByVal num As String)

它在我的电脑上工作,但它不适用于我的老板的电脑。 所有的文件名称和路径规范的拼写都很好。 我的DLL是在Microsoft Visual C ++ 6.0中编译的。 问题是 – “找不到文件/运行时错误53”的常见原因是调用应用程序无法找到有问题的DLL实际上依赖于的DLL! 我给了我的老板我以DEBUG模式编译的DLL – 在这种情况下,DLL使用了很多在普通计算机上不常见的DLL的其他调试版本。 当我给我的老板RELEASE版本的DLL,它工作的很好! 另见: http : //software.intel.com/zh-cn/forums/showthread.php?t=42472

那么这可能太晚了,但是需要考虑一些问题

1)“调用约定”必须正确匹配。 这有几个不同的方面,其中一些是:

a)s / r和Arg名称的大小写。

b)停顿调用约定。 在你的代码中,你使用了一些“混合”的东西,似乎缺少一些位。

例如,试试这个

 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 ! eg 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) 

注意为字符串len额外的Arg,这只出现在VBA一侧,只有当字符串通过ByVal(任何其他字符串传递,尤其是字符串数组是一个巨大的问题…可行,但准备一些作业) 。

此外,这里的字符串len只是在Arg位置的后面跟随字符串。 但是,如果num位于前面,那么NumLen的位置将会紧跟在Arg num之后,或者在Arg列表的末尾,这取决于调用约定。

另外,当你创建一个DLL时,编译器通常也会创建一个“Def”文件。 使用VBA / Fortran时,不需要直接访问Def文件。 然而,从里面看它会告诉你编译器认为你的s / r应该被调用的确切的“命名风格”。 例如,对于一些调用约定,Def文件可能会显示您的s / r的名称,如__fortrancall @ 12

…无论Def文件说什么,你必须使用的VBA声明别名“__fortrancall @ 12”

…这些事情需要对不同的调用约定/编译器进行长时间的讨论。

顺便说一句:我添加了“_XX”,纯粹是为了让实际的VBA UDF具有“明显的名字”,比如说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,那么您还必须在VBA端包含字符串长度ByVal Long(因为在Fortran中,字符串len是一个隐藏值),如上所示。

如果您知道如何在Fortran端使用(Cray)指针或变体将VBString转换为Fortran字符串等,则可以通过Ref传递,并且可以使用/不使用额外的StringLen ..长时间的讨论。

3)分发/连接到DLL的更一般和“确定”的方式是将XL表/模块转换为XLA …即插件。 然后,XLA和DLL(通常)放在相同的目录中,并通过工具/ Addins等将Addin添加到Excel中…浏览以确保正确的路径。

然后,您也可以从任何工作簿/表单中调用您的s / r,而不仅仅是一个工作簿。

我最近和ifort 14一样,当我编译时,问题就消失了

 ifort /dll /libs:static /threads 

而不是仅仅

 ifort /dll 

当DLL不依赖于系统路径上的另一个DLL(例如gfortran和MinGW32 \ bin中的一个DLL)时,通常会出现消息“找不到文件”。 但是我没有在这里找到这样的依赖,很奇怪。