Compiled .so for boost python cannot find module

2019-06-19 18:55发布

I am trying to wrap c++ code into python, just one class to export with two functions. I compiled to to map.so and when I try to import map get error like noise

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: ./map.so: undefined symbol: _ZTIN5noise6module6ModuleE

My c++ directory looks like (noise is dowwnloaded source code and all code is inside src)

/ map.cpp
  real_map.h
  real_map.cpp
  noise/
       src/
          .h and .cpp and new directory

my CMakeLists.txt looks like

project (map)
cmake_minimum_required(VERSION 2.8)

find_package(PythonLibs)
include_directories (${PYTHON_INCLUDE_DIRS})

find_package(Boost 1.45.0 COMPONENTS python)
include_directories (${Boost_INCLUDE_DIRS})


add_library (
    map SHARED  
    WrappedMediumMapTile.cpp
)

target_link_libraries (medium_map
    boost_python
    ${PYTHON_LIBRARIES}
    ${Boost_LIBRARIES}
)

Does anyone have a clue what is a problem ?

My .cpp class which I want to wrap

#include <list>
#include <iostream>
#include <vector>
#include <utility>
#include <map>

#include "noise/src/noise.h"
#include "noiseutils/noiseutils.h"

class MapTile
{
public:
    MapTile(float x1, float y1, float x2, float y2);
    ~MapTile();
    void genHeightMaps(int resX, int resY);


    bool isPassable(float x, float y);
    bool isBuildable(float x, float y);


protected:
    float parentX1;
    float parentY1;
    float parentX2;
    float parentY2;

private:
    noise::module::RidgedMulti baseMountainTerrain;
    noise::module::ScaleBias mountainTerrain;
    noise::module::Billow baseFlatTerrain;
    noise::module::ScaleBias flatTerrain;
    noise::module::Perlin lowFreqBaseTerrainType;
    noise::module::Perlin mediumFreqBaseTerrainType;
    noise::module::Perlin highFreqBaseTerrainType;
    noise::module::Select baseTerrainType;
    noise::module::ScaleBias terrainType;
    noise::module::Const zero;
    noise::module::Perlin highHigh;
    noise::module::Select finalTerrain;
    noise::module::Select goldWoodDeposits;
    noise::utils::NoiseMap heightMapTerrain;
    noise::utils::NoiseMap heightMapGoldWood;
    noise::utils::Image image;
};

and my wrap python

#include <boost/python.hpp>

#include "MapTile.h"
#include "noise/src/noise.h"
#include "noiseutils/noiseutils.h"

using namespace boost::python;

BOOST_PYTHON_MODULE(map) // module name
{
     class_<MapTile>("MapTile", init<float, float, float, float>())
        .def("isPassable", &MapTile::isPassable)
        .def("isBuildable", &MapTile::isBuildable);
};

Noise library is downloaded from http://sourceforge.net/projects/libnoise/files/libnoise%20sources/1.0.0/libnoisesrc-1.0.0.zip/download?use_mirror=garr&download= and used noise folder

2条回答
贪生不怕死
2楼-- · 2019-06-19 19:27

I had got a similar error when I hadn't ensured proper scope. It looks like you're importing a lot of headers, just check again.

查看更多
神经病院院长
3楼-- · 2019-06-19 19:40

Importing something in python, runs some other codes, and in this case it's loading and executing some C++ code.

When you load a library (as .so) or run an executable in linux, it looks for symbols in all the shared objects that it's linked to. When the executable or the library is being compiled and linked, it checks for all the symbols while linking, in the directories that are listed for looking for those shared objects.

But there is also another concept which is the path of those shared objects. When you have some dependencies to some libraries, not only the name of those .so files can be stored, but also the path to them can be stored in your .so or executable. It's more like a list of paths to look for dependencies rather than a per-shared-object path.

You can check for the paths and libraries of you binary using ldd.

If during the compilation for some reason finds those .so files, but the path to them is not added to the library/executable, then while loading the library or running the executable you will get an error for not being able to find a symbol. You can use this switch in gcc to add a path to the binary:

-Wl,-rpath,your_path

And you can see more info here

I feel like this might be your problem, cause you are only setting the inlude_dir variables in your CMAKE.

查看更多
登录 后发表回答