使用Windows 7,Matlab R2011a(32位)和Open Watcom Version 1.8,我试图编译一个调用Fortran代码的C MEX文件。
按照Matlab网站(support link)发布的指示,我首先使用以下命令编译了一个Fortran对象文件:
wfl386 -c -fpi87 -SC getqpf.f
然后我尝试将目标文件链接到许多C文件。所有C文件都正确编译,但我收到以下链接错误。未定义的引用用于从getqpf.f
中的子例程调用的C文件中的函数。例如,QESTM
被定义为其中一个C文件中的函数int qestm_()
。
q_estimate.c
文件包含MEX程序的入口点函数。我们的想法是让入口点函数调用getqpf.f
中的子例程。 getqpf.f
中的子例程调用其他文件中的C代码函数。
我如何摆脱未定义的引用?
>> mex q_estimate.c paul2.c paul2_L1.c paul6.c paul6_L1.c runavg.c fit_slope.c getqpf.obj
Open Watcom Linker Version 1.8
Portions Copyright (c) 1985-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.
See http://www.openwatcom.org/ for details.
loading object files
searching libraries
Error! E2028: QESTM is an undefined reference
Error! E2028: QESTM1 is an undefined reference
Error! E2028: QESTF is an undefined reference
Error! E2028: QESTF1 is an undefined reference
creating a Windows NT dynamic link library
file getqpf.obj(E:\DEVELOPMENT-FINAL\EXPERIMENTS\test-Q-analysis\getqpf.f): undefined symbol QESTM
file getqpf.obj(E:\DEVELOPMENT-FINAL\EXPERIMENTS\test-Q-analysis\getqpf.f): undefined symbol QESTM1
file getqpf.obj(E:\DEVELOPMENT-FINAL\EXPERIMENTS\test-Q-analysis\getqpf.f): undefined symbol QESTF
file getqpf.obj(E:\DEVELOPMENT-FINAL\EXPERIMENTS\test-Q-analysis\getqpf.f): undefined symbol QESTF1
C:\PROGRA~2\MATLAB\R2011A~1\BIN\MEX.PL: Error: Link of 'q_estimate.mexw32' failed.
答案 0 :(得分:1)
由于C对命名区分大小写,您是否尝试将该函数定义为int QESTM_()
而不是int qestm_()
?
答案 1 :(得分:1)
仅为了完整起见:Open Watcom F77程序员指南(可用here)指定:
默认符号命名约定因编译器而异。 Watcom C / C ++在变量名的开头加上下划线字符前缀,并在编译过程中在函数名末尾附加下划线。 Watcom FORTRAN 77将符号转换为大写。辅助编译指示可用于解决此不一致问题。
然后该文档继续解释如何使Watcom C / C ++编译器对外部符号执行相同的转换,以便C代码可以调用Fortran例程,以及使Fortran代码符号外部为C-喜欢这样,以便Fortran代码可以调用C例程。目前尚不清楚这种机制是否可以反向运行,即强制Fortran例程符号以特定情况导出。
要实现这一点,您可以使用一个特殊的编译指示,它可以用来处理外部符号得到的情况:
*$pragma aux cname "!_"
其中cname
是外部符号的名称,在C代码中定义。 "!_"
告诉编译器使用带有添加下划线的名称的小写版本(这假设C文件是使用Open Watcom C / C ++编译器编译的)。如果C编译器没有附加下划线,那么您应该使用"!"
代替。因此,如果您将以下内容添加到Fortran代码中,则不需要在C代码中使用大写名称:
*$pragma aux qestm "!_"
*$pragma aux qestm1 "!_"
*$pragma aux qestf "!_"
*$pragma aux qestf1 "!_"
也可以像这样指定外部名称:
*$pragma aux qestm "qEsTm_"
或
*$pragma aux qestm "qEsTm"
取决于C编译器是否添加下划线。然后,Fortran代码将引用有趣名称qestm
(或qEsTm_
)下的qEsTm
符号。当然,您必须使用qEsTm
作为C函数的名称。这里的要点是为引号内的名称保留了大小写。