LNK2001 error when using boost::numpy

2019-07-27 07:40发布

问题:

I am trying to call a C++ .dll from Python and return a numpy array. I am using

  • Anaconda 2.7 x64
  • Visual Studio 2013 update 5
  • boost 1.63.0 prebuileded for lib64-msvc-12.0

I managed to compile this simple example frome here and run it in Python:

#include "stdafx.h"
#define BOOST_PYTHON_STATIC_LIB
#include <boost/python.hpp>

char const* greet()
{
    return "hello, world";
}

BOOST_PYTHON_MODULE(test)
{
    using namespace boost::python;
    def("greet", greet);
}

I am unsure about the #define BOOST_PYTHON_STATIC_LIB but without it python could not open the pyd file. I suspected that python could not resolve the references to MSVCR120.dll in the dynamic build, but I am just guessing.

Next step was to include <boost/python/numpy.hpp> and follow this instuctions and start with just creating a numpy::ndarray. Yes, I am aware that void is in contradiction to the intention of getting values, I just wanted to keep things as simple as possible.

#include <boost/python/numpy.hpp>
namespace p = boost::python;
namespace np = boost::python::numpy;

void getNPArray()
{
    Py_Initialize();
    np::initialize();
    p::object tu = p::make_tuple('a', 'b', 'c');
    np::ndarray const example_tuple = np::array(tu);
    return;
}

The import and namespace declarations compile without error. At next step I encountered the linker error. While Py_Initialize() worked fine, the np::initialize() causes the linker to throw

error LNK2001: unresolved external symbol "void __cdecl boost::python::numpy::initialize(bool)" (?initialize@numpy@python@boost@@YAX_N@Z)

And np::ndarray const example_tuple = np::array(tu) causes a

error LNK2001: unresolved external symbol "class boost::python::numpy::ndarray __cdecl boost::python::numpy::array(class boost::python::api::object const &)" (?array@numpy@python@boost@@YA?AVndarray@123@AEBVobject@api@23@@Z)

As the linker is perfectly happy with the first example I am toally confused about what is going on here. I also tried to comment out all parts from the first example and just compile the second part witout any change in behaviour.

Any hints on how to make my linker happy are highly appreciated.

[update - issue solved] It turned out that the source of the errors is simply that the probuild version of boost comes without a libboost_numpy-vc120-mt-1_63.lib so i followed the instructions here to build it. Using this parameters:

b2 -j8 --toolset=msvc-12.0  release link=static runtime-link=static address-model=64 --build-type=complete stage --with-python 

The import which is now working for me looks like this:

#define BOOST_PYTHON_STATIC_LIB  
#define BOOST_LIB_NAME "boost_numpy"
#include <boost/config/auto_link.hpp>
#include <boost/python/numpy.hpp>

回答1:

The required library is not pulled in automatically by boost_numpy like it is for other Boost components. To fix this, place these lines in one of your source files:

#define BOOST_LIB_NAME "boost_numpy"
#include <boost/config/auto_link.hpp>

This will use Boost's automatic linking feature to determine the appropriate boost_numpy library for your build configuration (such as libboost_numpy-vc120-mt-1_63.lib) and generate a #pragma that asks your linker to include it.

Those two lines probably should be included in boost/python/numpy.hpp. The omission may be a bug there.

Incidentally, those lines can be repeated as many times as necessary, changing the definition LIB_BOOST_NAME each time, to include any other missing Boost libraries. (auto_link.hpp intentionally does not use an include guard, thus permitting this type of usage.)