首页 > 解决方案 > 如何使用 PyO3 解组 PyCodeObject?

问题描述

我正在阅读 .pyc 文件,并且需要能够解组代码对象。当我尝试将未编组的内容向下转换PyAny为 时PyCodeObject,我收到以下错误消息:

error[E0277]: the trait bound `pyo3::ffi::code::PyCodeObject: pyo3::type_object::PyTypeInfo` is not satisfied
   --> src/lib.rs:179:47
    |
179 |         let code = *(loads(py, &code_buffer)?.downcast::<PyCodeObject>()?);
    |                                               ^^^^^^^^ the trait `pyo3::type_object::PyTypeInfo` is not implemented for `pyo3::ffi::code::PyCodeObject`
    |
    = note: required because of the requirements on the impl of `for<'py> pyo3::conversion::PyTryFrom<'py>` for `pyo3::ffi::code::PyCodeObject`

error[E0277]: the trait bound `pyo3::ffi::code::PyCodeObject: pyo3::instance::PyNativeType` is not satisfied
   --> src/lib.rs:179:47
    |
179 |         let code = *(loads(py, &code_buffer)?.downcast::<PyCodeObject>()?);
    |                                               ^^^^^^^^ the trait `pyo3::instance::PyNativeType` is not implemented for `pyo3::ffi::code::PyCodeObject`
    |
    = note: required because of the requirements on the impl of `for<'py> pyo3::conversion::PyTryFrom<'py>` for `pyo3::ffi::code::PyCodeObject`

这样做的正确方法是什么?

MCVE

use pyo3::{ffi::PyCodeObject, marshal::loads, Python};

fn main() {
    let gil_guard = Python::acquire_gil();
    let py = gil_guard.python();
    let code_buffer = &include_bytes!("__pycache__/test.cpython-37.pyc")[16..];
    let code = *(loads(py, &code_buffer)
        .unwrap()
        .downcast::<PyCodeObject>()
        .unwrap());
}

创建测试文件:

  1. 创建一个 .py 文件
  2. 在 Python 中导入模块(例如python(3) -c 'import ...'
  3. __pycache__文件夹中应该有一个 .pyc 文件
  4. 将调用中代码中的路径替换为include_bytes!实际路径

版本信息

标签: pythonrustunmarshallingffipyo3

解决方案


我想我已经想出了如何做到这一点:

let code_ptr = loads(py, &code_buffer)?.as_ptr() as *mut PyCodeObject;
// This should be valid, since PyCodeObject is Copy, as long as the refcount is positive
let code = unsafe { *code_ptr };

推荐阅读