带有链接 dll 的 object 文件中的符号大小写是否重要?
Does symbol capitalization matter in object files with a linked dll?
我正在尝试让 gfortran 编译器在 Windows 上在 MATLAB 中运行以创建 mex files。不支持 Gfortran,但支持英特尔 Fortran 编译器,这让我相信 Fortran 编译器应该能够使用 MATLAB 库编译 Fortran 源代码。
如 my previous question, I get an "undefined reference" error for every symbol that should come from the MATLAB libraries. I thought this was an error with the preprocessor not getting invoked as suggested in a question on MathWorks Answers 中所述,但在进一步研究这个问题后,我认为这不是问题所在,因为错误指的是 "mxisnumeric800" 之类的东西,它是 fintrf.h header.
我检查了从所需库导出的符号,libmx.dll 和 libmex.dll,使用 dumpbin。导出的符号包括两个接近 mxisnumeric800:
Section contains the following exports for libmx.dll
...
1431 596 0009F200 MXISNUMERIC800
...
1747 6D2 000ABC24 mxIsNumeric_800
...
我能理解为什么 mxIsNumeric_800 由于额外的下划线而不会被读作相同的符号,但是大写也有区别吗?
您遇到的问题是 Fortran 是一种 大小写敏感的语言。所以如果你有一个子程序 foo
:
subroutine foo(x)
real :: x
end subroutine foo
您可以使用以下任何一种方式调用它:
call foo(x)
call FOO(x)
call fOo(x)
当您使用此函数构建目标文件或库时,符号名称将取决于编译器。对于 Linux 系统上的 Gfortran,它将始终将符号名称小写并在其后添加下划线,例如
foo_
在 Windows 系统上它的行为会有所不同(参见 here and here),甚至不同的编译器也会有不同的想法。
那么现在呢,这一切意味着什么?
这意味着当你编写一个子程序调用时:
call mxIsNumeric_800(arg1, arg2, arg3)
Gfortran 将尝试 link 它针对符号 mxisnumeric_800_
而不是您期望的符号。在过去,这通常会导致非常不便携的丑陋黑客。 Fortran 2003 通过引入 BIND
属性以明确的方式解决了这个问题。允许程序员通知编译器该对象应作为非 Fortran 对象处理的属性(参见 Section 15.5 of the F2008 standard)。
使用此属性,您现在可以定义一个 Fortran 完全理解的接口,并且编译器知道在哪里可以找到相应的符号及其各自的大小写敏感性。例如
interface
subroutine mxisnumeric(arg1,arg2,arg3) BIND(C, NAME="mxIsNumeric_800")
use, intrinsic :: iso_c_binding
implicit none
real(c_float) :: arg1
integer(c_int) :: arg2
character(c_char) :: arg3
end subroutine mxisnumeric
end interface
可以找到更多详细信息 here。
我正在尝试让 gfortran 编译器在 Windows 上在 MATLAB 中运行以创建 mex files。不支持 Gfortran,但支持英特尔 Fortran 编译器,这让我相信 Fortran 编译器应该能够使用 MATLAB 库编译 Fortran 源代码。
如 my previous question, I get an "undefined reference" error for every symbol that should come from the MATLAB libraries. I thought this was an error with the preprocessor not getting invoked as suggested in a question on MathWorks Answers 中所述,但在进一步研究这个问题后,我认为这不是问题所在,因为错误指的是 "mxisnumeric800" 之类的东西,它是 fintrf.h header.
我检查了从所需库导出的符号,libmx.dll 和 libmex.dll,使用 dumpbin。导出的符号包括两个接近 mxisnumeric800:
Section contains the following exports for libmx.dll
...
1431 596 0009F200 MXISNUMERIC800
...
1747 6D2 000ABC24 mxIsNumeric_800
...
我能理解为什么 mxIsNumeric_800 由于额外的下划线而不会被读作相同的符号,但是大写也有区别吗?
您遇到的问题是 Fortran 是一种 大小写敏感的语言。所以如果你有一个子程序 foo
:
subroutine foo(x)
real :: x
end subroutine foo
您可以使用以下任何一种方式调用它:
call foo(x)
call FOO(x)
call fOo(x)
当您使用此函数构建目标文件或库时,符号名称将取决于编译器。对于 Linux 系统上的 Gfortran,它将始终将符号名称小写并在其后添加下划线,例如
foo_
在 Windows 系统上它的行为会有所不同(参见 here and here),甚至不同的编译器也会有不同的想法。
那么现在呢,这一切意味着什么?
这意味着当你编写一个子程序调用时:
call mxIsNumeric_800(arg1, arg2, arg3)
Gfortran 将尝试 link 它针对符号 mxisnumeric_800_
而不是您期望的符号。在过去,这通常会导致非常不便携的丑陋黑客。 Fortran 2003 通过引入 BIND
属性以明确的方式解决了这个问题。允许程序员通知编译器该对象应作为非 Fortran 对象处理的属性(参见 Section 15.5 of the F2008 standard)。
使用此属性,您现在可以定义一个 Fortran 完全理解的接口,并且编译器知道在哪里可以找到相应的符号及其各自的大小写敏感性。例如
interface
subroutine mxisnumeric(arg1,arg2,arg3) BIND(C, NAME="mxIsNumeric_800")
use, intrinsic :: iso_c_binding
implicit none
real(c_float) :: arg1
integer(c_int) :: arg2
character(c_char) :: arg3
end subroutine mxisnumeric
end interface
可以找到更多详细信息 here。