1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use crate::object::*;
use crate::{PyCFunctionObject, PyMethodDefPointer, METH_METHOD, METH_STATIC};
use std::os::raw::c_int;
use std::ptr::addr_of_mut;

pub struct PyCMethodObject {
    pub func: PyCFunctionObject,
    pub mm_class: *mut PyTypeObject,
}

#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    pub static mut PyCMethod_Type: PyTypeObject;
}

#[inline]
pub unsafe fn PyCMethod_CheckExact(op: *mut PyObject) -> c_int {
    (Py_TYPE(op) == addr_of_mut!(PyCMethod_Type)) as c_int
}

#[inline]
pub unsafe fn PyCMethod_Check(op: *mut PyObject) -> c_int {
    PyObject_TypeCheck(op, addr_of_mut!(PyCMethod_Type))
}

#[inline]
pub unsafe fn PyCFunction_GET_FUNCTION(func: *mut PyObject) -> PyMethodDefPointer {
    debug_assert_eq!(PyCMethod_Check(func), 1);

    let func = func.cast::<PyCFunctionObject>();
    (*(*func).m_ml).ml_meth
}

#[inline]
pub unsafe fn PyCFunction_GET_SELF(func: *mut PyObject) -> *mut PyObject {
    debug_assert_eq!(PyCMethod_Check(func), 1);

    let func = func.cast::<PyCFunctionObject>();
    if (*(*func).m_ml).ml_flags & METH_STATIC != 0 {
        std::ptr::null_mut()
    } else {
        (*func).m_self
    }
}

#[inline]
pub unsafe fn PyCFunction_GET_FLAGS(func: *mut PyObject) -> c_int {
    debug_assert_eq!(PyCMethod_Check(func), 1);

    let func = func.cast::<PyCFunctionObject>();
    (*(*func).m_ml).ml_flags
}

#[inline]
pub unsafe fn PyCFunction_GET_CLASS(func: *mut PyObject) -> *mut PyTypeObject {
    debug_assert_eq!(PyCMethod_Check(func), 1);

    let func = func.cast::<PyCFunctionObject>();
    if (*(*func).m_ml).ml_flags & METH_METHOD != 0 {
        let func = func.cast::<PyCMethodObject>();
        (*func).mm_class
    } else {
        std::ptr::null_mut()
    }
}