有没有办法将 PyTypeObject 从 Python 库继承到 CPython 中的自定义类型?

问题描述

我正在尝试在 cpython 中创建一个自定义类型,该类型继承自 Python 中已定义的类型对象。到目前为止,我的方法是使用 public class RomanNumberUtils { static String romanNumeral; static int decimalNum; public static void main(String args[]) { RomanNumberUtils roman = new RomanNumberUtils(); roman .convertRomanToDecimal(); roman .printRoman(romanNumeral); } public void convertRomanToDecimal () { Scanner scan = new Scanner(system.in); System.out.print("Enter a Roman number: "); romanNumeral = scan.nextLine(); romanNumeral = romanNumeral.toupperCase(); int l= romanNumeral.length(); int num=0; int prevIoUsnum = 0; for (int i=l-1;i>=0;i--) { char x = romanNumeral.charat(i); x = Character.toupperCase(x); switch(x) { case 'I': prevIoUsnum = num; num = 1; break; case 'V': prevIoUsnum = num; num = 5; break; case 'X': prevIoUsnum = num; num = 10; break; case 'L': prevIoUsnum = num; num = 50; break; case 'C': prevIoUsnum = num; num = 100; break; case 'D': prevIoUsnum = num; num = 500; break; case 'M': prevIoUsnum = num; num = 1000; break; } if (num<prevIoUsnum) {decimalNum= decimalNum-num;} else decimalNum= decimalNum+num; } } public static void printRoman (String romanNumeral){ System.out.println ("The equivalent of the Roman numeral "+romanNumeral+" is "+decimalNum); } } ,然后访问 PyImport_ImportModule 并将其设置为我的 PyTypeObject 中的 tp_base 属性

导入:

PyTypeObject

继承:

PyTypeObject typeObj = {...} // PrevIoUsly defined PyTypeObject for a fallback

int init() {
    PyObject* obj = PyImport_ImportModule("<absolute_path_to_python_module>");
    if (obj && PyObject_Hasstring(obj,"<python_type_object>")) {
        PyTypeObject* type_ptr = (PyTypeObject*) PyObject_GetAttrString(obj,"<python_type_object>");
        typeObj = *type_ptr;
    }
    if (PyType_Ready(&typeObj) < 0) return -1;
    ... // Other initialization stuff
}

自定义类型能够继承函数,但在 PyTypeObject CustomType = { ... // Initialization stuff .tp_base = &typeObj; }; 上失败。当我尝试访问自定义类型的 isinstance(CustomType(),TypeObj) 属性时,它会引发分段错误

解决方法

类型由身份标识,而不是值。当您尝试执行 typeObj = *type_ptr; 时,即使它“有效”,typeObj 的内存地址与 *type_ptr 不同,并且永远不会被视为相同的类型。您需要保留身份。

将您的代码更改为:

PyTypeObject fallback_type_obj = {...} // Previously defined PyTypeObject for a fallback
PyTypeObject *type_ptr = NULL;

int init() {
    PyObject* obj = PyImport_ImportModule("<absolute_path_to_python_module>");
    if (obj && PyObject_HasString(obj,"<python_type_object>")) {
        type_ptr = (PyTypeObject*) PyObject_GetAttrString(obj,"<python_type_object>");
    }
    if (type_ptr == NULL) {
        if (PyType_Ready(&fallback_type_obj) < 0) return -1;
        type_ptr = &fallback_type_obj;
    }
    ... // Other initialization stuff
}

然后创建一个使用 type_ptr 作为基础的堆类型(静态/全局类型不起作用,因为 type_ptr 没有被静态初始化为任何有用的东西)。