Need help getting started with Boost.Python

2019-04-05 19:28发布

问题:

I'm trying to build my first Boost.Python example.

#include <iostream>
#include <boost/python.hpp>

using namespace boost::python;


class Hello {

public:
    std::string greet() {
        std::cout << "Hello World" << std::endl;
    }
};


BOOST_PYTHON_MODULE(hello)
{
    class_<Hello>("Hello")
        .def("greet", &Hello::greet);
}

int main() {
    std::cout << "Boost.Python Test" << std::endl;
    Hello hello;
    hello.greet();
    return 0;
}

EDIT: Python development headers were missing, as @cdhowie has pointed out. I have found and included the required header files. Now the linker is complaining:

   10:43:58 **** Build of configuration BoostPythonTest-DPar for project BoostPythonTest 

****
make all 
Building file: ../src/BoostPythonTest.cpp
Invoking: GCC C++ Compiler
/usr/local/bin/g++-4.7 -I/usr/local/Cellar/python3/3.3.0/Frameworks/Python.framework/Versions/3.3/include/python3.3m -I/usr/include -I/usr/local/Cellar/gcc/4.7.2/gcc/include/c++/4.7.2 -O0 -g3 -p -pg -Wall -c -fmessage-length=0 -std=c++11 -MMD -MP -MF"src/BoostPythonTest.d" -MT"src/BoostPythonTest.d" -o "src/BoostPythonTest.o" "../src/BoostPythonTest.cpp"
Finished building: ../src/BoostPythonTest.cpp

Building target: libBoostPythonTest-DPar.dylib
Invoking: MacOS X C++ Linker
/usr/local/bin/g++-4.7 -L/usr/local/Cellar/python3/3.3.0/Frameworks/Python.framework/Versions/3.3/lib/python3.3/config-3.3m -L/usr/local/Cellar/python3/3.3.0/Frameworks/Python.framework/Versions/3.3/lib -L/usr/local/Cellar/boost/1.51.0/lib -std=c++11 -Xlinker -ldl -framework CoreFoundation -lpython3.3m -dynamiclib -o "libBoostPythonTest-DPar.dylib"  ./src/BoostPythonTest.o   -lpython3.3m -lboost_python-mt -lpython3.3
Undefined symbols for architecture x86_64:
  "boost::python::detail::init_module(PyModuleDef&, void (*)())", referenced from:
      _PyInit_hello in BoostPythonTest.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
make: *** [libBoostPythonTest-DPar.dylib] Error 1

I've already linked to -lpython3.3m -lboost_python-mt -lpython3.3 - what else is missing?

EDIT: I think I've linked to everything which python3.3-config lists. Linking still does not work because of missing symbols.

回答1:

When this particular linker error occurs, it is often the result of the application building against one version of Python, such as Python 3.x header files, while the boost_python library was built against a difference version, such as 2.x.

In boost/python/module_init.hpp, the init_module function has the following signature when building against Python 3.x:

PyObject* boost::python::detail::init_module(PyModuleDef&, void(*)());

and the following signature when building against Python 2.x:

PyObject* boost::python::detail::init_module(char const* name, void(*)());

As can be seen in the implementation , only one of the functions will be present in the Boost.Python library. Thus, given the Boost.Python library is being linked in, and the linker is only complaining about not being able to resolve the 3.x init_module function, then it is very likely that the Boost.Python library was built against a Python 2.x version, while the application code has been built against Python 3.x header files. You can verify this by dumping the Boost.Python library's symbols and check the init_module signature.

To resolve this, build the application with the same version of Python from which Boost.Python was built. In this case, either:

  • Build the application with Python 2.x header files and link against Python 2.x libraries.
  • Build Boost.Python against Python 3.x. This documentation describes the steps to build Boost, and this documentation goes into detail for Boost.Python. It may be necessary to explicitly provide the Python executable from which Boost.Python will build against during the bootstrap process by using the --with-python argument.


回答2:

You are missing the Python development headers. Your Linux distribution should have a package for them. (For example, python-dev on Debian or Ubuntu.)



回答3:

You are building a shared library, because that is what a binary Python module is. For that, you need -shared or -dynamic (check the docs) and you should not have a main() function.

Further, if that doesn't help and you still have the linker errors, use "objdump -T --demangle /path/to/lib" to find out which symbols a library contains and whether it has those that you need. Also check the output of "ldd", which lists dependent shared objects. This should give you a hint which library or libraries to link.

On my system, I also have a program called "python-config" and "python2.7-config". Check if you have something similar, because this script knows which libraries to link at least for python. A similar tool is pkg-config, which is more general and might provide information for boost, too.



回答4:

Not sure if this is the way to do it, but it seems that the PY_VERSION_HEX is set wrong. What happens if you

#define PY_VERSION_HEX 0x03300000

before including the boost.python headers in your BoostPythonTest.cpp?



回答5:

You also have to link with Boost.System, as well as any other libraries mentioned by the linker. Also, try other compilers, such as Clang(https://svn.boost.org/trac/boost/ticket/7536), which comes with XCode(Latest Clang location in XCode 4.5). Also, try posting your makefile. Another attempt would be using bjam/b2 instead of make.