我正试图为一个C++库创建一个Python封装器。弓箭 使用 Boost.Python.Python.Python 我的代码灵感来自于另一个包装器 pyDBoW3 到一个非常相似的图书馆 DBoW3下面是我目前能够做的:pyBoW3包装器在我的系统上工作--我可以把它导入到Python中,让它做自己的事情。弓箭 包装器,我试图创建的包装器在barebones中可以工作,但是当我试图链接一个使用底层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&)
包装器代码的主要片段是:
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. 在 repo 上有一个编译脚本,地址是 https:/github.comvik748pyfbow 这可以让它很快地进行。
现在,如果我评论出 voc_creator->create(*voc, training_features, std::string("NA"), voc_creator_params);
然而,如果这一行不加注释,代码就会编译和链接,但导入python时就会出现上述错误。
以下是我试过的所有方法。
boost::noncopyable
-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)'
TLDR:fbow库findcmake在设置fbar_LIBS变量,而我的包装器在读取fbar_LIBRARIES变量。
如何调试:根据 @ead 的建议和提供的链接,我添加了以下内容 set( CMAKE_VERBOSE_MAKEFILE on)
中的参数 CMakeLists.txt
而在运行 make 时,我能够看到 cmake_link_script。 我将它与 pyDBoW3 包中的脚本进行了比较,发现其中的 -L 参数较少。 进一步研究后,我发现 fbow_LIBRARIES
是空的。 在检查软件包的 fbowConfig.cmake 时,它设置的是 fbow_LIBS 变量。 换了名字之后,所有的问题都解决了。
谢谢 @ead 的帮助。