python - Boost.Python TypeError : __init__() should return None not 'NoneType' - but no obvious linker or version problem

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

我正在为 python3.7 安装的 boost 接口(interface)构建一个用于 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'

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

最少的代码(在 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'

最佳答案

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

在您的链接行中,替换 -lpython<version>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<version>m .由于这种不一致,我暂时只使用我自己的扩展数据。

学分 :

感谢 Nehal J Wani最初报告此解决方案的人here .

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

关于python - Boost.Python TypeError : __init__() should return None not 'NoneType' - but no obvious linker or version problem,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61463744/

相关文章:

python - 使用 PySpark 并行自定义函数

C++ 目标用简单的语法 T.g 抛出错误

c++ - "Pancake glutton"练习;如果用户输入两个或更多相等的值怎么办

python - 使用列表中的搜索词从文本中获取字数的最快方法?

python - 为什么我的查询无法使用 RDFlib 运行

Python正则表达式匹配列表但不与字典列表

python - python统计txt文件中某个单词的出现次数

C++:不允许 void 的部分函数特化 - 替代解决方案?

python /MySQL : Escaping strings used as parameters in raw database queries

python - 在python中查找并删除以特定子字符串开头和结尾的字符串