为 Python 写一个 C++ 扩展模块( 三 )


 

  1.  
    PyObject *MyClass_new(PyTypeObject *type, PyObject *args, PyObject *kwds){
     
  2.  
    std::cout << "MtClass_new() called!" << std::endl;
     
  3.  
     
  4.  
    MyClassObject *self;
     
  5.  
    self = (MyClassObject*) type->tp_alloc(type, 0);
     
  6.  
    if(self != NULL){ // -> 分配成功
     
  7.  
    // 赋初始值
     
  8.  
    self->m_value = https://www.isolves.com/it/cxkf/yy/Python/2023-01-03/0;
     
  9.  
    self->m_myclass = NULL;
     
  10.  
    }
     
  11.  
    return (PyObject*) self;
     
  12.  
    }
     
 
实际的初始化发生在MyClass_init中,它对应于 Python 中的 docs.python.org 方法:
 
  1.  
    int MyClass_init(PyObject *self, PyObject *args, PyObject *kwds){
     
  2.  
     
  3.  
    ((MyClassObject *)self)->m_value = https://www.isolves.com/it/cxkf/yy/Python/2023-01-03/123;
     
  4.  
     
  5.  
    MyClassObject* m = (MyClassObject*)self;
     
  6.  
    m->m_myclass = (MyClass*)PyObject_Malloc(sizeof(MyClass));
     
  7.  
     
  8.  
    if(!m->m_myclass){
     
  9.  
    PyErr_SetString(PyExc_RuntimeError, "Memory allocation failed");
     
  10.  
    return -1;
     
  11.  
    }
     
  12.  
     
  13.  
    try {
     
  14.  
    new (m->m_myclass) MyClass();
     
  15.  
    } catch (const std::exception& ex) {
     
  16.  
    PyObject_Free(m->m_myclass);
     
  17.  
    m->m_myclass = NULL;
     
  18.  
    m->m_value = https://www.isolves.com/it/cxkf/yy/Python/2023-01-03/0;
     
  19.  
    PyErr_SetString(PyExc_RuntimeError, ex.what());
     
  20.  
    return -1;
     
  21.  
    } catch(...) {
     
  22.  
    PyObject_Free(m->m_myclass);
     
  23.  
    m->m_myclass = NULL;
     
  24.  
    m->m_value = https://www.isolves.com/it/cxkf/yy/Python/2023-01-03/0;
     
  25.  
    PyErr_SetString(PyExc_RuntimeError, "Initialization failed");
     
  26.  
    return -1;
     
  27.  
    }
     
  28.  
     
  29.  
    return 0;
     
  30.  
    }
     
 
如果你想在初始化过程中传递参数,必须在此时调用 docs.python.org 。简单起见,本例将忽略初始化过程中传递的所有参数 。在函数的第一部分中,PyObject指针(self)被强转为MyClassObject类型的指针,以便访问其他成员 。此外,还分配了 C++ 类的内存,并执行了构造函数 。
注意,为了防止内存泄漏,必须仔细执行异常处理和内存分配(还有释放) 。当引用计数将为零时,MyClass_dealloc函数负责释放所有相关的堆内存 。在文档中有一个章节专门讲述关于 C 和 C++ 扩展的内存管理 。


推荐阅读