Я показываю класс C ++ Python, используя pybind11
.
Он принимает numpy.array
в своем конструкторе и получает указатель на свои внутренние данные. (Он не копирует данные).
#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;
};
У меня есть другой класс, который принимает 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_;
};
Здесь два класса доступны для python с помощью pybind11:
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
из 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, который у меня есть (вот ссылка для загрузки рассматриваемого файла рассола):
>>> 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 полностью доволен моим файлом рассола:
>>> 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
и травление, это отлично работает - Я нарезал свой «недействительный» фрейм данных и могу получить подмножество, которое отлично работает
В моих данных есть что-то, чему питон доволен, но вызывает SEGV в C ++.
Как я могу это диагностировать?
numpy.random.rand
и т. Д.). - person Steve Lorimer   schedule 13.07.2018