【问题标题】:Boost.Python TypeError: __init__() should return None not 'NoneType' - but no obvious linker or version problemBoost.Python TypeError: __init__() 应该返回 None 而不是 'NoneType' - 但没有明显的链接器或版本问题
【发布时间】:2020-04-27 16:34:25
【问题描述】:

我正在为 python3.7 安装的 boost 接口构建一个用于 python 访问的 c++ 引擎。这是为:

Mac OS Mojave  -  10.14.6
Python 3.7.4
Conda 4.8.3 (only crashes in a conda-built environment)
C++: clang version 11.0.0 (clang-1100.0.33.17)
Boost version 1.67.0

python 代码失败(据我所知)__init__ 函数中,使用

Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: __init__() should return None, not 'NoneType'

其他堆栈溢出报告(参见下面的参考书目)和 github 线程表明,典型问题是 python 版本之间的 .dylibs 中的错误链接,或者没有提供任何答案。但是dylib不兼容似乎不是这里的情况。 otool -L(或 ldd)表示库绑定是一致的,一切都应该很好。这是代码和构建步骤。

最少的代码(在 python 版本上有一个小的“检查”功能):

#include <iomanip>
#include <patchlevel.h>
#include <boost/python/def.hpp>
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>

namespace R3 {
  class DistanceType {
  public:
    DistanceType(double _val = 0) : val(_val) {}
    double get() const { return val; }
    void set(double _val) { val = _val; }
  private:
    double val;
  };
  void pyversion() {
    int hexversion = PY_VERSION_HEX;
    std::cout << "compiled with python version: " << PY_VERSION
      << " (hex version code) " << std::hex << std::setw(8) << hexversion << '\n';
  }
}

BOOST_PYTHON_MODULE(simplepython) {
  using namespace boost::python;

  class_<R3::DistanceType>("DistanceType", init<double>())
    .add_property("value", &R3::DistanceType::get, &R3::DistanceType::set)
  ;

  boost::python::def("pyversion", R3::pyversion);
}

以下是构建和运行代码的结果:

>: g++ -I/opt/anaconda3/include/python3.7m -I/opt/anaconda3/include/python3.7m -O2 -fPIC -std=c++11  -Iinclude   -c -o objs/simplepython.o src/simplepython.cpp
>: g++ -Wl,-rpath,/opt/anaconda3/lib -shared -o lib/simplepython.so objs/simplepython.o -L/opt/anaconda3/lib -Llib -lpython3.7m -ldl -framework CoreFoundation -lboost_python37 -lboost_numpy37
>: cd lib
>: python -c 'import simplepython as R3; R3.pyversion(); R3.DistanceType(1)'
compiled with python version: 3.7.4 (hex version code)  30704f0
Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: __init__() should return None, not 'NoneType'

参考书目 - 相关堆栈溢出问题报告:

TypeError: __init__() should return None, not 'NoneType' with Python Boost

Is this Boost::Python (Python 3.7) error "__init__() should return None, not 'NoneType'" a linking problem?

Boost.Python __init__() should return None, not 'NoneType'

【问题讨论】:

    标签: python c++ python-3.x boost anaconda


    【解决方案1】:

    原来错误出在静态链接库 libpythonversion>。为了与 conda 和非 conda 环境兼容,c++/boost 构建应该动态解析这些符号。以下为我解决了它:

    在您的链接行中,将 -lpython&lt;version&gt;m 替换为 -undefined dynamic_lookup.

    CMake

    链接行在/build/mybinary/CMakeFiles/myextension_py.dir/link.txt 中可用。目前看来,链接命令必须在 CMake 版本3.17.2 中手动编辑。

    注意

    如果您使用$(shell python3-config --libs) 派生-l 路径,则可能会导致解决方案失效:在3.8 版之前,它包含-lpython&lt;version&gt;m。由于这种不一致,我暂时只使用我自己的扩展数据。

    学分

    感谢最初报告此解决方案的Nehal J Wanihere

    感谢 newkid 的 CMake 编辑 - 我从其他帖子中复制了它。

    【讨论】:

      猜你喜欢
      • 2013-12-24
      • 2019-08-09
      • 1970-01-01
      • 2019-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-13
      • 2021-08-13
      相关资源
      最近更新 更多