这个 Boost::Python (Python 3.7) 错误

更新

我不打算添加这个作为答案,因为我还没有在技术上解决这个问题。但是由于我现在已经花了 2.5 天的时间来尝试使用 boost-python3 进行工作,我已经失去了忍受它的意愿。


我刚刚遇到pybind11(我之前对 python 绑定工具的冗长搜索如何没有发现它,我不知道)并且正在使用它。2.5 天的痛苦与 <20 分钟安装和构建他们的cmake 示例相比......所有特定的 python-version-dependency-hell 都消失了。


它在语法上与 boost-python 相似,但更易于管理、更快、仅包含标题并且功能更丰富。


夏天!


原始问题

我正在使用 boost::python 在 python 3.7.2 中绑定一个类。


类导入成功但实例化它会出现以下错误:


<my-terminal>$ python

Python 3.7.2 (default, Feb 14 2019, 17:36:47) 

[Clang 10.0.0 (clang-1000.11.45.5)] on darwin

Type "help", "copyright", "credits" or "license" for more information.

>>> import classes

>>> t = classes.World()

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

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

>>> 

这是classes.cpp:


#include <boost/python.hpp>

#include <boost/python/list.hpp>

#include <boost/python/extract.hpp>

#include <string>

#include <sstream>

#include <vector>


struct World

{

    void set(std::string msg) { mMsg = msg; }

    void many(boost::python::list msgs) {

        long l = len(msgs);

        std::stringstream ss;

        for (long i = 0; i<l; ++i) {

            if (i>0) ss << ", ";

            std::string s = boost::python::extract<std::string>(msgs[i]);

            ss << s;

        }

        mMsg = ss.str();

    }

    std::string greet() { return mMsg; }

    std::string mMsg;

};


using namespace boost::python;


BOOST_PYTHON_MODULE(classes)

{

    class_<World>("World")

        .def("greet", &World::greet)

        .def("set", &World::set)

        .def("many", &World::many)

    ;

};


斯蒂芬大帝
浏览 152回答 3
3回答

月关宝盒

在此处为使用 Anaconda 或 Conda-Forge 发行版的人添加答案:python 解释器在libpythonXY库中静态链接。这就是为什么它使 python 二进制文件与其他发行版不同的原因。OP 报告的问题的解决方法是使用:-undefined dynamic_lookup代替:-lpythonXY您正在创建 Python C/C++ 扩展,而不是嵌入 Python 解释器。所以你不应该链接到 python 库。Pybind11 正确处理了这个问题。有关更多信息,请参阅以下内容:https://gitlab.kitware.com/cmake/cmake/issues/18100https://github.com/ContinuumIO/anaconda-issues/issues/9078一个旁注,python 3.8 添加了一个额外的标志:--embed然后才-lpythonXY在输出中添加:$ python3.8-config --libs-ldl -framework CoreFoundation$ python3.8-config --libs --embed-lpython3.8 -ldl -framework CoreFoundation

撒科打诨

我正在遵循一个类似的例子,我采用了这里的 Makefile 。我已经安装python 3.7.4,并boost-python通过brew上macOS。为了解决这个NoneType问题,我按照以下步骤操作:1.检查Python路径要检查python路径,请使用which python如果输出看起来不像下面的(brew的python安装路径)/usr/local/opt/python/libexec/bin/python将PATH变量设置为export PATH="/usr/local/opt/python/libexec/bin:$PATH"Python再次检查路径是否与上面的类似。2. 检查编译标志下面是采用的Makefile. 注意LIB变量。如果boost-python标志是-lboost_python,请将其更改为-lboost_python37。CPP = clang++PYLIBPATH = $(shell python-config --exec-prefix)/lib# LIB = -L$(PYLIBPATH) $(shell python-config --libs) -lboost_pythonLIB = -L$(PYLIBPATH) $(shell python-config --libs) -lboost_python37OPTS = $(shell python-config --include) -O2default: hello.sohello.so: hello.o&nbsp; &nbsp; $(CPP) $(LIB) -Wl,-rpath,$(PYLIBPATH) -shared $< -o $@hello.o: hello.cpp Makefile&nbsp; &nbsp; $(CPP) $(OPTS) -c $< -o $@clean:&nbsp; &nbsp; rm -rf *.so *.o.PHONY: default clean重新编译C++代码并运行python脚本。这个NoneType问题应该消失了。希望这可以帮助。注意如果您正在使用anaconda并希望PATH在上述更改后恢复变量,请尝试export PATH="~/anaconda3/bin:$PATH"你anaconda的路径可能不同。

皈依舞

跟进Nehal对基于 Anaconda 的构建的回答。重新阅读 cmake 的 FindPython 文档显示Python::Module目标已添加到 cmake 3.15 中以创建模块。这意味着 CMakeLists.txt 应该是:set(Python3_FIND_VIRTUALENV FIRST)find_package(Python3 REQUIRED Development)find_package(Boost REQUIRED python3)add_library(classes MODULE classes.cpp)target_link_libraries(classes PRIVATE Python3::Module Boost::python3)显然,这Python3::Python是为了在另一个应用程序中嵌入 Python。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python