【发布时间】:2015-08-22 17:18:56
【问题描述】:
我主要尝试在更简单的设置中模仿this。没有运气。
我写了一个简单的fortran代码:
subroutine POWERTWO (n, nsquared)
!DEC$ ATTRIBUTES DLLEXPORT :: POWERTWO
integer, intent(in) :: n
integer, intent(out) :: nsquared
nsquared = n*n
return
end subroutine POWERTWO
我用 gfortran 编译如下:
gfortran -m32 -dynamiclib ./tmp.f90 -o ./tmp.dylib
注意我的gfortran配置如下:
COLLECT_LTO_WRAPPER=/usr/local/lvm/gcc-5.2.0/libexec/gcc/x86_64-apple-darwin14.4.0/5.2.0/lto-wrapper
Target: x86_64-apple-darwin14.4.0
Configured with: ../configure --prefix=/usr/local/lvm/gcc-5.2.0 --enable-checking=release --with-gmp=/usr/local/lvm/gmp-6.0.0 --with-mpfr=/usr/local/lvm/mpfr-3.1.2 --with-mpc=/usr/local/lvm/mpc-1.0.3 --enable-languages=c,c++,fortran,objc,obj-c++ --with-isl=/usr/local/lvm/isl-0.14 --with-cloog=/usr/local/lvm/cloog-0.18.4
Thread model: posix
gcc version 5.2.0 (GCC)
在 dylib 所在的同一文件夹中,我有一个 excel 2011 xslm 电子表格,在 VBA 中我输入了以下代码:
Declare Function powertwo CDecl Lib "tmp.dylib" (n As Long, ByVal nsquared As Long)
Function VBA_UDFPowerTwo(n As Long) As Long
Dim res As Long
res = 0
Call powertwo(n, res)
VBAUDFPowerTwo = res
End Function
现在,在单元格 A2 中执行公式 =VBA_UDFPowerTwo(A1) 给我一个 #VALUE!。如果我将整个路径放在 VBA 中的 dylib 中,结果相同:
Declare Function powertwo CDecl Lib "/Users/XXXXXX/Documents/GITHUBRepos/DYLIBS/MyFirstDylib/tmp.dylib" (n As Long, ByVal nsquared As Long)
或作为
Declare Function powertwo CDecl Lib "Mackintosh HD:Users:XXXXXX:Documents:GITHUBRepos:DYLIBS:MyFirstDylib:tmp.dylib" (n As Long, ByVal nsquared As Long)
如果我将ByVal 替换为ByRef,则相同。甚至一个
Declare Function powertwo CDecl Lib "Mackintosh HD:Users:ludwigvonmises:Documents:GITHUBRepos:DYLIBS:MyFirstDylibt:tmp.dylib" Alias "POWERTWO" (n As Long, ByRef nsquared As Long)
没有让我开心。我错过了什么或做错了什么?
我在 dylib 上做了一个nm 并得到以下信息:
00000fa4 t ___x86.get_pc_thunk.ax
00000f87 T _powertwo_
U dyld_stub_binder
而nm -gU 给了我:
00000f87 T _powertwo_
在打开 excel 并触发 A2 单元格中的计算时,Console.app 告诉我以下内容:
22/08/15 19:37:32,892 Microsoft Excel[2971]: WARNING: The Gestalt selector gestaltSystemVersion is returning 10.9.5 instead of 10.10.5. Use NSProcessInfo's operatingSystemVersion property to get correct system version number.
Call location:
22/08/15 19:37:32,892 Microsoft Excel[2971]: 0 CarbonCore 0x96a01291 ___Gestalt_SystemVersion_block_invoke + 135
22/08/15 19:37:32,893 Microsoft Excel[2971]: 1 libdispatch.dylib 0x92c4f0b5 dispatch_once_f + 251
22/08/15 19:37:32,893 Microsoft Excel[2971]: 2 libdispatch.dylib 0x92c500d8 dispatch_once + 31
22/08/15 19:37:32,893 Microsoft Excel[2971]: 3 CarbonCore 0x9697a69d _Gestalt_SystemVersion + 1050
22/08/15 19:37:32,893 Microsoft Excel[2971]: 4 CarbonCore 0x969797c0 Gestalt + 150
22/08/15 19:37:32,893 Microsoft Excel[2971]: 5 MicrosoftComponentPlugin 0x01bdb27e McpInitLibrary_ + 505
22/08/15 19:37:32,893 Microsoft Excel[2971]: 6 MicrosoftComponentPlugin 0x01bdb0ae McpInitLibrary_ + 41
和otool -L tmp.dylib 显示以下内容:
./tmp.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/local/lvm/gcc-5.2.0/lib/i386/libgfortran.3.dylib (compatibility version 4.0.0, current version 4.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
/usr/local/lvm/gcc-5.2.0/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/local/lvm/gcc-5.2.0/lib/i386/libquadmath.0.dylib (compatibility version 1.0.0, current version 1.0.0)
编辑
求助于:
Declare Function powertwo_ CDecl Lib "Macintosh HD:Users:XXXXXX:Documents:GITHUBRepos:DYLIBS:MyFirstDylib:tmp.dylib" (n As Long, ByRef nsquared As Long)
正如Ken Thomases建议的那样,在单元格A2中触发计算时导致excel崩溃,这至少表明导出的函数名称不是powertwo而是powertwo_,并且excel的VBA确实加载了tmp.dylib。
【问题讨论】:
-
当 Excel 尝试加载您的插件时,它是否将任何内容写入控制台日志?您可以查看 /Applications/Utilities/Console.app。
otool -L tmp.dylib显示什么?我怀疑它依赖于不在标准搜索路径中的库(请参阅dyld(1) man page)。 -
@KenThomases 感谢您对这样一个微本地化主题的兴趣!我在问题的末尾添加了 Console.app 的输出(以前从未使用过,所以我可能做错了)和
otool -L tmp.dylib的输出,供您查看。顺便说一句,我没有加载任何插件,我只是编写了一个在 .dylib 中编译的 .f90 文件,正如我在问题中所描述的那样。 -
嗯。控制台输出可能是良性的,并且与显然无法正常工作的插件无关。您可以在尝试使用您的插件后使用
vmmap -w -interleaved <pid of Excel>检查Excel 进程,以查看tmp.dylib是否已成功加载到进程中。我注意到nm输出有一个下划线前缀和后缀_powertwo_。前缀对于 C 符号是正常的,例如,dlsym()会处理它。后缀似乎不寻常。对Declare Function powertwo_ …有效吗? -
这里的大多数 Fortran 人员不会检查所有版本和编译器标记(
fortran90、gfortran等...) - 您应该考虑标记fortran而不是gcc5或gfortran。有关更多信息,请参阅此内容:meta.stackoverflow.com/questions/261912/…。 -
@Ross 完成。即使我不完全确定问题与 fortran 相关。无论如何。
标签: excel vba macos fortran dylib