【问题标题】:Undefined Symbol when wrapping a C++ module using Boost.python when importing to python导入到 python 时使用 Boost.python 包装 C++ 模块时的未定义符号
【发布时间】:2020-05-11 04:29:30
【问题描述】:

我正在尝试使用 Boost.Python 为 C++ 库 fbow 创建 Python 包装器。我的代码灵感来自另一个包装器pyDBoW3 到一个非常相似的库DBoW3。 到目前为止,这是我能做的: pyBoW3 包装器在我的系统上工作——我可以将它导入 Python 并让它做它的事情。 我正在尝试创建的 pyfbow 包装器在准系统中工作,但是一旦我尝试链接一个使用底层 fbow 库中的某些内容的函数,它就会抛出:

$ python -c "import pyfbow.so"
ImportError: dlopen(/Users/vik748/pyfbow/build/pyfbow.so, 2): Symbol not found: __ZN4fbow10Vocabulary10saveToFileERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE
  Referenced from: /Users/vik748/pyfbow/build/pyfbow.so
  Expected in: flat namespace
 in /Users/vik748/pyfbow/build/pyfbow.so

$ nm pyfbow.dylib | grep __ZN4fbow10Vocabulary10saveToFileERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE
                 U __ZN4fbow10Vocabulary10saveToFileERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE


$ c++filt -n __ZN4fbow10Vocabulary10saveToFileERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE
fbow::Vocabulary::saveToFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)

包装器代码的主要sn-p是:

class Vocabulary
{
public:
    Vocabulary(int k = 10, int L = 6, int nthreads = 1, int maxIters = 0, bool verbose = true){
        voc_creator_params.k = k;
        voc_creator_params.L = L;
        voc_creator_params.nthreads = nthreads;
        voc_creator_params.maxIters = maxIters;
        voc_creator_params.verbose = verbose;
    }
    ~Vocabulary() {
        //delete voc;
        //delete voc_creator;
    }
    void create(const  std::vector<cv::Mat>   &training_features ) {
        std::cout << "Creating a " << voc_creator_params.k << "^" << voc_creator_params.L << " vocabulary..." << std::endl;
       voc_creator->create(*voc, training_features, std::string("NA"), voc_creator_params);
    }

    fbow::Vocabulary * voc;
    fbow::VocabularyCreator * voc_creator;
    fbow::VocabularyCreator::Params voc_creator_params;
};

namespace fs {
    namespace python {
        BOOST_PYTHON_MODULE(pyfbow)
        {
            // Main types export
            fs::python::init_and_export_converters();
            py::scope scope = py::scope();

            // Class
            py::class_<Vocabulary>("Vocabulary")
                .def(py::init< py::optional<int, int, int, int, bool> >(
                    (py::arg("k") = 10, py::arg("L") = 5, py::arg("nthreads") = 1,
                     py::arg("maxIters") = 0, py::arg("verbose") = true )))
                .def("create", &Vocabulary::create);
        }
    } // namespace fs
} // namespace python

如果您想在您的系统上进行测试,唯一的依赖项是 boost-python 和 opencv。在 https://github.com/vik748/pyfbow 的 repo 上有一个构建脚本,可以让它很快运行。

现在,如果我注释掉 voc_creator-&gt;create(*voc, training_features, std::string("NA"), voc_creator_params); 一切正常,代码编译,链接,我就可以将包导入 Python。 但是,如果该行未注释,则代码会编译并链接,但导入 python 会引发上述错误。

以下是我尝试过的所有方法:

  1. here 所述,我已尝试添加boost::noncopyable
  2. here 所述,我已将代码添加到底层 fbow 库正在使用的几个空虚函数中。
  3. 我认为this 暗示不同的编译器可能会导致问题,但由于代码编译时带有注释行,我认为这不是问题。
  4. 按照here 的建议,我还尝试将 pyfbow 和 fbow 合并到同一个包和 CMakeLists.txt 中,但这也没有帮助。
  5. 此外,根据其他几个不同的 SO 帖子,我尝试了一堆链接器标志 -Wl -export_dynamic -flat_namespace -export-dynamic 等。

我想尽办法解决这个问题,我欢迎任何调试想法。 干杯!

根据@ead 的建议,我正在添加来自ld --trace-symbol 的输出

ld pyfbow.so --trace-symbol=_ZN4fbow17VocabularyCreator6createERNS_10VocabularyERKSt6vectorIN2cv3MatESaIS5_EERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS0_6ParamsE
pyfbow.so: reference to _ZN4fbow17VocabularyCreator6createERNS_10VocabularyERKSt6vectorIN2cv3MatESaIS5_EERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS0_6ParamsE
ld: warning: cannot find entry symbol _start; not setting start address
pyfbow.so: undefined reference to `fbow::VocabularyCreator::create(fbow::Vocabulary&, std::vector<cv::Mat, std::allocator<cv::Mat> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, fbow::VocabularyCreator::Params)'

【问题讨论】:

  • 与其在不了解问题的情况下尝试不同的建议,不如看看你的链接器命令(也许把它放在这里)并分析它,有一系列可能的原因:stackoverflow.com/q/12573816/5769463使用 --trace-symbol (--trace-symbol=symbol ) 跟踪链接器看到符号的顺序。
  • @ead 我已经添加了 --trace-symbol 的输出,还有其他想法可以找到根本原因吗?
  • 我的建议是添加到您的链接器标志中,以便您了解在链接扩展时会发生什么,而不是在它创建之后。你知道你的链接器命令是什么样子的吗?您是否在我链接的问题中解决了可能的原因并将其与您的链接命令进行了比较?
  • 所以当我将它作为SET_TARGET_PROPERTIES(pyfbow PROPERTIES PREFIX "" LINK_FLAGS "--trace-symbol=_ZN4fbow17VocabularyCreator6createERNS_10VocabularyERKSt6vectorIN2cv3MatESaIS5_EERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS0_6ParamsE") 添加到CMakeLists.txt 时,它会抛出c++: error: unrecognized command line option ‘--trace-symbol=,那么将它添加到CMakeLists.txt 的正确方法是什么?我也在研究您提供的链接中的建议。
  • 如果你使用 g++ Fronten 链接,你可以阅读文档如何将选项传递给链接器,可能是前缀“-Wl”或类似的

标签: linker cython wrapper boost-python


【解决方案1】:

TLDR:fbow 库 findcmake 正在设置 fbar_LIBS 变量,而我的包装器正在读取 fbar_LIBRARIES 变量。

如何调试: 根据@ead 的建议和提供的链接,我在CMakeLists.txt 中添加了set( CMAKE_VERBOSE_MAKEFILE on) 参数,并在运行make 时能够查看cmake_link_script。我将它与 pyDBoW3 包中的那个进行了比较,发现 -L 参数更少。在进一步调查中,我发现fbow_LIBRARIES 是空的。在检查包的 fbowConfig.cmake 时,它​​正在设置 fbow_LIBS 变量。切换名称解决了所有问题。

感谢@ead 的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多