错误pybind11简单示例:涉及hpp header

error pybind11 simple example: hpp header involved

我正在尝试 运行 pybind11 的一个简单示例。

下面是我的编译代码(来自pybind11官网):

c++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup `python3 -m pybind11 --includes` wrapper.cpp -o example`python3-config --extension-suffix`

我得到三个文件。

funcs.cpp

#include "funcs.hpp"

int add(int i, int j) {
    return i + j;
};

funcs.hpp

int add(int i, int j);

wrapper.cpp

#include <pybind11/pybind11.h>
#include "funcs.hpp"

namespace py = pybind11;

PYBIND11_MODULE(example, m){
    m.def("add", &add, "A function which adds two numbers");
}

以及 运行 测试

的 .py 文件

main.py

import example

if __name__  =='__main__':
    print(example.add(1, 2))

但是,这会引发错误

$python main.py
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    import example
ImportError: dlopen(/Users/nirvana_kwai/dev/dev_setup/dark_magic/pybindtest/example.cpython-36m-darwin.so, 2): Symbol not found: __Z3addii
  Referenced from: /Users/nirvana_kwai/dev/dev_setup/dark_magic/pybindtest/example.cpython-36m-darwin.so
  Expected in: flat namespace
 in /Users/nirvana_kwai/dev/dev_setup/dark_magic/pybindtest/example.cpython-36m-darwin.so

如果我只将 wrapper.cpp 中的一行从 #include "funcs.hpp" 更改为 #include "funcs.cpp"。该错误已修复。我真的不明白问题出在哪里。当我尝试简化案例并将所有代码合并到一个文件中时,我 google 经常修复它。

有人可以帮我吗?

因为我是 Whosebug 的新手,我的声誉不允许我添加评论,所以写一个建议作为答案。如果@Lihaonan 它解决了你的问题,那就太好了,如果没有,就留下评论说。谢谢

我有两个建议供您尝试:

a) 将声明放在 extern "C" 下并重新编译 运行 你的 程序。所以你在 func.hpp 中的代码看起来像:

extern "C"
{
    int add(int i, int j);
}

我建议进行此更改,假设由于 name mangling 你正面临此问题。

b) 我不确定为什么你没有在编译步骤中包含 func.cpp 但是当 运行 时间环境是无法找到其中一项声明的定义。所以你的编译步骤应该是这样的:

c++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup `python3 -m pybind11 --includes` wrapper.cpp func.cpp -o example`python3-config --extension-suffix`

对于希望使用 setuptools 而不是手动编译的人,请将其插入到您的 pybind11 项目的 setup.py 中:

ext_modules = [
    Pybind11Extension(
        <module_name>,
        sorted(glob("src/*.cpp")),
        define_macros=[('VERSION_INFO', __version__)],
    ),
]

sorted(glob("src/*.cpp")) 然后链接到 src/ 中的所有 .cpp 个文件。您当然可以根据需要修改 glob() 中的调用。