为 f2py 使用 C++ 源时未定义的符号

Posted

技术标签:

【中文标题】为 f2py 使用 C++ 源时未定义的符号【英文标题】:Undefined symbol when using C++ source for f2py 【发布时间】:2018-01-04 13:51:58 【问题描述】:

我可以用 f2py 包装一个 C 函数,如下所示:

foo.c

#include <stdio.h>

void func(int n, int * a) 
    printf("%d\n", n);

对应的接口文件是

foo.pyf

python module foo
interface
subroutine func(n, a)
    intent(c) func
    intent(c)

    integer, intent(hide)                  :: n = shape(a,0)
    real(kind=8), dimension(n), intent(in) :: a
end subroutine func
end interface
end python module foo

然后,我执行f2py foo.pyf -c foo.c -m foo,它会创建 Python 库,例如代码

import numpy as np
import foo

foo.func( np.ones(3) )

如您所愿打印3

问题:更改foo.cfoo.cpp 导致未定义符号

通过将foo.c 的扩展名更改为foo.cpp,我注意到

f2py foo.pyf -c foo.cpp -m foo

调用g++ 而不是gcc。美好的。但是,之后当我在 Python 中执行 import foo 时,我看到了:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: ./foo.so: undefined symbol: func_

我必须应用什么魔法才能使f2py 与 C++ 代码一起工作?有可能吗?

补充说明:

如果我删除接口文件中的intent(c) foo 行,那么foo.c 会产生相同的行为,即它与f2py 一起编译时,从Python 导入时会出现相同的未定义符号错误。

【问题讨论】:

您究竟为什么要尝试通过f2pyC(和C++)函数生成Python 绑定?该程序用于为 Fortran 函数生成绑定。 getting started guide 表示它可以用于 C 和 Fortran。请参阅this also(虽然有些过时)。 【参考方案1】:

啊,这几乎肯定是名称修改的问题。

C++ 名称保存在链接器中,其“错位”名称比“C”对应名称要复杂得多,以便区分 C++ 允许的重载名称,即使是非类函数。

您可以将函数声明为extern "C",以便使用C 命名约定导出它。函数的主体仍然可以使用 c++ 功能,但它应该对 f2py 或类似的可见。

请注意,这会阻止您在该函数名称上使用 C++ 名称重载。

【讨论】:

是的,这行得通。谢谢。我在foo.cpp 中的void func ... 之前添加了extern "C" 当然,如果你能找到一个cpp2py,那就更好了。

以上是关于为 f2py 使用 C++ 源时未定义的符号的主要内容,如果未能解决你的问题,请参考以下文章

ImportError:在 python 中导入 swigged c++-class 时未定义的符号

为 C 库生成 Python SWIG 绑定时未定义的符号

链接到 MacOS 上预编译的 QuantLib 二进制文件时未定义的 Boost 符号

为 C++ 编译时未找到符号,但为 C 找到了符号

尝试使用 dlopen 加载库时未定义的符号

尝试使用 Cython 扩展时未定义的符号