为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

斯蒂芬大帝 2021-11-09 19:49:32
更新我不打算添加这个作为答案,因为我还没有在技术上解决这个问题。但是由于我现在已经花了 2.5 天的时间来尝试使用 boost-python3 进行工作,我已经失去了忍受它的意愿。我刚刚遇到pybind11(我之前对 python 绑定工具的冗长搜索如何没有发现它,我不知道)并且正在使用它。2.5 天的痛苦与 <20 分钟安装和构建他们的cmake 示例相比......所有特定的 python-version-dependency-hell 都消失了。它在语法上与 boost-python 相似,但更易于管理、更快、仅包含标题并且功能更丰富。夏天!原始问题我正在使用 boost::python 在 python 3.7.2 中绑定一个类。类导入成功但实例化它会出现以下错误:<my-terminal>$ pythonPython 3.7.2 (default, Feb 14 2019, 17:36:47) [Clang 10.0.0 (clang-1000.11.45.5)] on darwinType "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)    ;};
查看完整描述

3 回答

?
月关宝盒

TA贡献1772条经验 获得超5个赞

在此处为使用 Anaconda 或 Conda-Forge 发行版的人添加答案:


python 解释器在libpythonXY库中静态链接。这就是为什么它使 python 二进制文件与其他发行版不同的原因。


OP 报告的问题的解决方法是使用:


-undefined dynamic_lookup

代替:


-lpythonXY

您正在创建 Python C/C++ 扩展,而不是嵌入 Python 解释器。所以你不应该链接到 python 库。Pybind11 正确处理了这个问题。


有关更多信息,请参阅以下内容:


https://gitlab.kitware.com/cmake/cmake/issues/18100

https://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


查看完整回答
反对 回复 2021-11-09
?
撒科打诨

TA贡献1934条经验 获得超2个赞

我正在遵循一个类似的例子,我采用了这里的 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_python

LIB = -L$(PYLIBPATH) $(shell python-config --libs) -lboost_python37

OPTS = $(shell python-config --include) -O2


default: hello.so



hello.so: hello.o

    $(CPP) $(LIB) -Wl,-rpath,$(PYLIBPATH) -shared $< -o $@


hello.o: hello.cpp Makefile

    $(CPP) $(OPTS) -c $< -o $@


clean:

    rm -rf *.so *.o


.PHONY: default clean


重新编译C++代码并运行python脚本。这个NoneType问题应该消失了。


希望这可以帮助。


注意

如果您正在使用anaconda并希望PATH在上述更改后恢复变量,请尝试


export PATH="~/anaconda3/bin:$PATH"

你anaconda的路径可能不同。


查看完整回答
反对 回复 2021-11-09
?
皈依舞

TA贡献1851条经验 获得超3个赞

跟进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。


查看完整回答
反对 回复 2021-11-09
  • 3 回答
  • 0 关注
  • 151 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信