1

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>
Community
  • 1
  • 1
user_na
  • 2,154
  • 1
  • 16
  • 36
  • 2
    Boost build decides whether to build the boost-numpy library as part of the boost-python library based on whether executing python -c "import sys; sys.stderr = sys.stdout; import numpy; print(numpy.get_include())" succeeds or not. See https://github.com/boostorg/build/blob/e22a75c8fd83f0e52adea4f48ef5f9fbbdf5b72c/src/tools/python.jam#L838-L857 – Fedor Jun 16 '21 at 14:45

1 Answers1

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.)

JohnSpeeks
  • 735
  • 6
  • 14
  • 1
    Works like charm. I can't express my gratitute for your answer! – user_na Mar 22 '17 at 12:33
  • unfortunatelly it turned out that it does not solve my issue. np::initialize() was commented out when i tested it the first time. – user_na Mar 23 '17 at 19:48
  • 1
    @user_na - Perhaps you need even more configuration options for your particular setup to include the correct library. You may need to `#define BOOST_DYN_LINK` also. Or you could include [this entire "config.hpp" file](https://raw.githubusercontent.com/boostorg/python/bd7b8ecba5c211c3361c4a9af82a7a527bed384e/include/boost/python/numpy/config.hpp) rather than just adding those two lines. Otherwise, pay attention to the exact errors you're getting. I'd bet they've changed. – JohnSpeeks Mar 23 '17 at 22:32
  • So I started a new project to trace the issue and in the clean project I got a message that libboost_numpy-vc120-mt-1_63.lib is missing using your additional define and include. And the lib was just not delivered with the prebuild version. Compiled it and it is now working. Your suggestion in the answer is still neccessary though to get it running. Thanks again for your help. I would upvote again if I could... – user_na Mar 24 '17 at 08:21