Как может actix Actor иметь PyO3 Python? - PullRequest
0 голосов
/ 12 сентября 2018

Я пытаюсь создать Actix Actor, который имеет интерпретатор PyO3 Python и объекты Py.

Вопрос в том, как правильно создать актер интерпретатора Python?

Я думаю, что ошибка вызванаАктерская черта определена статично.https://docs.rs/actix/0.7.4/actix/trait.Actor.html

Есть ли способ, согласно которому у актера или контекста для объекта требуется параметр жизни?

версия ржавчины: nightly-2018-09-04, версия actix: 0.7.4

Это текущий код.

extern crate actix;
extern crate actix_web;
extern crate pyo3;

use actix::prelude::*;
use actix_web::{http, server, ws, App, HttpRequest, HttpResponse, Error};
use pyo3::{Python, GILGuard, PyList};

struct WsActor<'a> {
    // addr: Addr<PyActor>,
    gil: GILGuard,
    python: Python<'a>,
    pylist: &'a PyList,
}
impl<'a> Actor for WsActor<'a> {
    type Context = ws::WebsocketContext<Self>;
}
fn attach_ws_actor(req: &HttpRequest<()>) -> Result<HttpResponse, Error> {
    let gil = Python::acquire_gil();
    let python = gil.python();
    let pylist = PyList::empty(python);
    let actor = WsActor {gil, python, pylist};
    ws::start(req, actor)
}
fn main() {
    let sys = actix::System::new("example");

    server::new(move || {
        App::new()
            .resource("/ws/", |r| r.method(http::Method::GET).f(attach_ws_actor))
    }).bind("0.0.0.0:9999")
    .unwrap()
        .start();
}

Этот код не может быть скомпилирован с этой ошибкой.

error[E0478]: lifetime bound not satisfied
  --> src/main.rs:15:10
   |
15 | impl<'a> Actor for WsActor<'a> {
   |          ^^^^^
   |
note: lifetime parameter instantiated with the lifetime 'a as defined on the impl at 15:6
  --> src/main.rs:15:6
   |
15 | impl<'a> Actor for WsActor<'a> {
   |      ^^
   = note: but lifetime parameter must outlive the static lifetime

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Как говорит Николай , вы можете хранить Py<PyList> объект в WsActor. Чтобы восстановить PyList, вы можете снова получить GIL и вызвать .as_ref(python) метод черты AsPyRef (который реализует Py<T>). Пример таков:

extern crate actix;
extern crate actix_web;
extern crate pyo3;

use actix::prelude::*;
use actix_web::{http, server, ws, App, HttpRequest, HttpResponse, Error};
use pyo3::{Python, PyList, Py, AsPyRef};

struct WsActor {
    // addr: Addr<PyActor>,
    pylist: Py<PyList>,
}
impl Actor for WsActor {
    type Context = ws::WebsocketContext<Self>;
}
impl StreamHandler<ws::Message, ws::ProtocolError> for WsActor {
    fn handle(&mut self, _: ws::Message, _: &mut Self::Context) {
        let gil = Python::acquire_gil();
        let python = gil.python();
        let list = self.pylist.as_ref(python);
        println!("{}", list.len());
    }
}

fn attach_ws_actor(req: &HttpRequest<()>) -> Result<HttpResponse, Error> {
    let gil = Python::acquire_gil();
    let python = gil.python();
    let pylist = PyList::empty(python);
    let actor = WsActor {
        pylist: pylist.into()
    };
    ws::start(req, actor)
}

fn main() {
    let sys = actix::System::new("example");

    server::new(move || {
        App::new()
            .resource("/ws/", |r| r.method(http::Method::GET).f(attach_ws_actor))
    }).bind("0.0.0.0:9999")
    .unwrap()
        .start();
}
0 голосов
/ 12 сентября 2018

Определение черты Актер равно

pub trait Actor: Sized + 'static { ... }

, что означает, что ваша жизнь 'a должна быть 'static.

Вот небольшой пример :

use std::marker::PhantomData;

trait Foo: Sized + 'static {
    fn foo();
}

struct Bar<'a> {
    _marker: PhantomData<&'a i32>,
}
impl<'a> Foo for Bar<'a> { //not possible
    fn foo() {}
}

struct Baz<'a> {
    _marker: PhantomData<&'a i32>,
}
impl Foo for Baz<'static> { //possible
    fn foo() {}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...