我最近在使用 Haskell FFI 到 C/C++ 时遇到了 C++ 内联函数的问题。也就是说,g++ 并没有真正内联声明的函数inline
,并为它们生成符号。最终,当 ghci 尝试加载调用内联函数的目标文件时,这会产生链接器错误:
Loading object (static) solveeq.o ... done
Loading object (dynamic) /usr/lib/gcc/x86_64-linux-gnu/4.6/libstdc++.so ... done
final link ... ghc: solveeq.o: unknown symbol `_ZN5Eigen8internal19throw_std_bad_allocEv'
在这里,只有头文件的 Eigen C++ 库中的_ZN5Eigen8internal19throw_std_bad_allocEv
一个inline
函数以某种方式被视为真正的函数并被赋予链接器符号。solveeq.o
是我的目标文件,它对那个函数进行(间接)调用。环境为 Ubuntu 12.04 64bit,ghc 7.4.1。
问题是这样的:我可以extern "C"
用来防止 C++ 修饰我自己的函数的函数名称。但是我不能/不应该更改其他人定义的 C++ 头文件(出于显而易见的原因)。在我看来,编译器不应该首先为这个内联定义创建一个函数来导致这个错误。原因很简单。如果有问题的函数是真正内联的,我不会收到链接器错误。如果编译器变得聪明并决定为它创建一个真正的函数,我会得到这样的错误(或者同一个函数的多个定义,正如我在别处读到的那样)。所以现在,编译/链接的正确性取决于编译器的心情。
另外,我认为像这样的链接器问题实际上破坏了仅包含标头的 C++ 库(它们吸引了它们的可移植性),因为现在它们不能使用extern "C"
.
这是 c++ 的设计问题还是只是 g++ 的问题?我的问题是,有没有办法防止 c++ 编译器或 g++ 不内联内联函数?例如,是否有一个命令行选项?(修改源代码是毫无疑问的,因为它们是库代码。)
另外,我很好奇 C++ STL 如何处理这个问题。它们也是仅标题吗?