Вектор пользовательской структуры в PyO3

Я новичок в Rust и PyO3 (из Python), так что это может быть очевидно для более опытных людей.

Я объявил структуру Pyclass в PyO3.

#[pyclass]
struct Block {
    start: i32,
    stop: i32,
}

Тогда я использую Block в функции ржавчины, которая принимает вектор Block и выводит вектор типа int (подпись ниже)

#[pyfunction]
fn from_blocks(block_list: Vec<Block>) -> Vec<i32>

Когда я компилирую, используя nightly-x86_64-apple-darwin Я получаю следующую ошибку:

#[pyfunction]
^^^^^^^^^^^^^ the trait `pyo3::FromPyObject<'_>` is not implemented for `std::vec::Vec<Block>`

Как мне это решить?

РЕДАКТИРОВАТЬ: Caio прав. Я сделал ошибку в отслеживании ошибки. Ранее я написал

Затем я использую Block в функции rust, которая берет вектор int и выводит вектор Block (подпись ниже)

#[pyfunction]
fn to_blocks(list: Vec<i32>) -> Vec<Block>

Но фактическая оскорбительная функция:

#[pyfunction]
fn from_blocks(block_list: Vec<Block>) -> Vec<i32>

Я обновил вопрос, чтобы сделать его более понятным.

3 ответа

Решение

FromPyObject предназначен для использования типами, которые могут быть извлечены из мира Python. Вот почему я думаю, что вы пытались написать fn to_blocks(list: Vec<Block>) -> Vec<i32> вместо fn to_blocks(list: Vec<i32>) -> Vec<Block>, Если это так, давайте перейдем к цепочке реализации.

FromPyObject имеет реализацию по умолчанию для любого &T, который реализует PyTryFrom и PyTryFrom имеет реализацию по умолчанию для любого T, который реализует PyTypeInfo. [pyclass] инвентарь PyObjectAlloc или же PyObjectWithFreeList в соответствии с impl_class метод и обе черты имеют PyTypeInfo черта связана. Следовательно, ваш класс / структура будет отлично работать со ссылками, например:

#[pyfunction]
fn to_blocks(list: Vec<&Block>) -> Vec<i32>

Вы можете увидеть в официальной документации это объяснение в кратком изложении.

FromPyObject реализуется различными типами, которые могут быть извлечены из ссылки на объект Python.

На какой версии PyO3 вы работаете? Ваш код работает на меня 0.5.3 а также 0.6.0-alpha.1,

Из-за этого я не могу проверить это, но я думаю, что вам нужно вернуть PyResult:

#[pyfunction]
fn to_blocks(list: Vec<i32>) -> PyResult<Vec<Block>>

Похоже, pyfunction атрибут генерирует код, который требует, чтобы возвращаемый тип реализовывал FromPyObject черта характера. Пока есть полная реализация FromPyObject for Vec<T> where T: FromPyObjectпохоже на код, сгенерированный для pyclass атрибут не включает реализацию FromPyObject для тебя Block тип.

Поскольку я незнаком с PyO3, за исключением нескольких минут, которые я только посмотрел на его документацию API, чтобы подтвердить этот ответ, я не уверен, как вам лучше всего получить FromPyObject реализация - возможно, есть derive для этого?

Другие вопросы по тегам