我正在使用pybind11
.
它numpy.array
在其构造函数中接受 a,并获取指向其内部数据的指针。(它不复制数据)。
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <iostream>
namespace py = pybind11;
struct Data
{
Data(const py::array_t<double, py::array::c_style| py::array::forcecast>& arr)
: p(arr.data())
{
std::cout << "arr=" << p << std::endl;
std::cout << "[0]=" << p[0] << std::endl;
}
const double* p;
};
我有另一个接受 a 的类const Data&
,从而可以访问数组数据。
struct Manager
{
Manager(const Data& data)
: data_(data)
{
const double* p = data_.p;
std::cout << "data.arr=" << p << std::endl;
std::cout << "data.[0]=" << p[0] << std::endl;
}
const Data& data_;
};
这里这两个类使用 pybind11 暴露给 python:
PYBIND11_MODULE(foo, m)
{
py::class_<Data>(m, "Data")
.def(py::init<const py::array_t<double, py::array::c_style| py::array::forcecast>&>());
py::class_<Manager>(m, "Manager")
.def(py::init<const Data&>());
}
这运作良好。我可以导入我的模块,Data
从 a 创建一个实例numpy.array
,然后将其传递给Manager
:
>>> import pandas
>>> import numpy
>>> import foo
>>> df = pandas.DataFrame(data = numpy.random.rand(990000, 7))
>>> d = foo.Data(df.values)
>>> c = foo.Manager(d)
我的脚本运行良好,您可以看到我的 C++ 代码访问numpy.array
数据并将其地址和第一个元素打印到标准输出:
arr=0x7f47df313010
[0]=0.980507
data.arr=0x7f47df313010
data.[0]=0.980507
我创建以上所有内容都是为了创建一个MCVE来说明我在下面遇到的问题。
但是,现在我加载了我拥有的 pandas DataFrame pickle 文件(这里是有问题的 pickle 文件的下载链接):
>>> import pandas
>>> import foo
>>> df = pandas.read_pickle('data5.pk')
>>> a = df.values
>>> d = foo.Data(a)
>>> c = foo.Manager(d)
我的 C++ 代码在尝试访问数组数据时崩溃。
这是标准输出:
arr=0x7f8864241010
arr[0]=7440.7
data.arr=0x7f8864241010
<dumps core>
所以指向数组的指针在 中是相同的Manager
,但是尝试取消引用指针会导致 SEGV。
通过 valgrind 运行它,valgrind 报告Access not within mapped region at address 0x7f8864241010
(即: 的地址numpy.array
)。
Python 对我的 pickle 文件非常满意:
>>> import pandas
>>> df = pandas.read_pickle('data5.pk')
>>> df.shape
(990000, 7)
>>> df
A B C D E \ 10000 7440.695240 15055.443905 14585.542158 3647.710616 8139.777981 10001 7440.607794 15055.356459 14585.454712 3647.623171 8139.690536 10002 7441.155761 15055.904426 14586.002679 3648.171138 8140.238503 10003 7440.430209 15055.178874 14585.277127 3647.445585 8139.512950 10004 7440.418058 15055.166724 14585.264977 3647.433435 8139.500800 10005 7440.906603 15055.655268 14585.753521 3647.921979 8139.989344 10006 7440.525167 15055.273832 14585.372085 3647.540543 8139.607908 ...
我一生都无法弄清楚我的泡菜文件出了什么问题。
- 我试过创建一个
numpy.array
酸洗,效果很好 - 我试过创建一个
pandas.DataFrame
酸洗,效果很好 - 我已经分割了我的“无效”数据框,我可以得到一个工作正常的子集
我的数据中有一些东西让 python 很高兴,但会导致 C++ 中的 SEGV。
我该如何诊断?