I am trying to create a Python wrapper for a C++ library fbow using Boost.Python. My code is inspired from another wrapper pyDBoW3 to a very similar library DBoW3. Here is what I am able to do so far: The pyBoW3 wrapper works on my system - I can import it into Python and have it do its thing. The pyfbow wrapper that I am trying to create works in the barebones, however as soon as I try to link a function that uses something from the underlying fbow library it throws:
$ 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&)
The main snippet of the wrapper code is:
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
If you'd like to test on your system the only dependencies are boost-python and opencv. There is a build script on the repo at https://github.com/vik748/pyfbow that can get it going very quickly.
Now if I comment out voc_creator->create(*voc, training_features, std::string("NA"), voc_creator_params);
everything works, code comiles, links and I am able to import the package into Python.
However if the line is left uncommented, the code compiles and links but importing into python throws the error above.
Here are all the things I have tried:
- As described here, I have tried adding
boost::noncopyable
- As described here, I have added code to a couple empty virtual functions that the underlying fbow library was using.
- I considered this suggesting that different compilers might be causing issues, but since the code compiles with the line commented, I don't think this is the issue.
- Going by the suggestion from here, I also tried combining both pyfbow and fbow into the same package and CMakeLists.txt but that didn't help either.
- Additionally, as per a couple different other SO posts, I have tried a bunch of linker flags
-Wl -export_dynamic -flat_namespace -export-dynamic
etc.
I am at my wits end trying to figure this out, I welcome any debugging ideas. Cheers!
As per @ead 's suggestion, I am adding output from 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)'