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


包装方法
从 Python 类中调用相关的 C++ 类方法很简单:
 

  1.  
    PyObject* MyClass_addOne(PyObject *self, PyObject *args){
     
  2.  
    assert(self);
     
  3.  
     
  4.  
    MyClassObject* _self = reinterpret_cast(self);
     
  5.  
    unsigned long val = _self->m_myclass->addOne();
     
  6.  
    return PyLong_FromUnsignedLong(val);
     
  7.  
    }
     
 
同样,PyObject参数(self)被强转为MyClassObject类型以便访问m_myclass,它指向 C++ 对应类实例的指针 。有了这些信息,调用addOne()类方法,并且结果以 docs.python.org 返回 。
3 种方法调试
出于调试目的,在调试配置中编译 CPython 解释器是很有价值的 。详细描述参阅 docs.python.org 。只要下载了预安装的解释器的其他调试符号,就可以按照下面的步骤进行操作 。
GNU 调试器
当然,老式的 opensource.com 也可以派上用场 。源码中包含了一个 github.com 文件,定义了一些选项和断点,另外还有一个 github.com 脚本,它会创建一个调试构建并启动一个 GDB 会话:
为 Python 写一个 C++ 扩展模块

文章插图
Gnu 调试器(GDB)对于 Python C 和 C++ 扩展非常有用
GDB 使用脚本文件 github.com 调用 CPython 解释器,它允许你轻松定义你想要使用 Python 扩展模块执行的所有操作 。
C++ 应用
另一种方法是将 CPython 解释器嵌入到一个单独的 C++ 应用程序中 。可以在仓库的 github.com 文件中找到:
 
  1.  
    int main(int argc, char *argv[], char *envp[])
     
  2.  
    {
     
  3.  
    Py_SetProgramName(L"DbgPythonCppExtension");
     
  4.  
    Py_Initialize();
     
  5.  
     
  6.  
    PyObject *pmodule = PyImport_ImportModule("MyModule");
     
  7.  
    if (!pmodule) {
     
  8.  
    PyErr_Print();
     
  9.  
    std::cerr << "Failed to import module MyModule" << std::endl;
     
  10.  
    return -1;
     
  11.  
    }
     
  12.  
     
  13.  
    PyObject *myClassType = PyObject_GetAttrString(pmodule, "MyClass");
     
  14.  
    if (!myClassType) {
     
  15.  
    std::cerr << "Unable to get type MyClass from MyModule" << std::endl;
     
  16.  
    return -1;
     
  17.  
    }
     
  18.  
     
  19.  
    PyObject *myClassInstance = PyObject_CallObject(myClassType, NULL);
     
  20.  
     
  21.  
    if (!myClassInstance) {
     
  22.  
    std::cerr << "Instantioation of MyClass failed" << std::endl;
     
  23.  
    return -1;
     
  24.  
    }
     
  25.  
     
  26.  
    Py_DecRef(myClassInstance); // invoke deallocation
     
  27.  
    return 0;
     
  28.  
    }
     
 
使用 docs.python.org,可以导入扩展模块并对其执行操作 。它允许你在本地 IDE 环境中进行调试,还能让你更好地控制传递或来自扩展模块的变量 。


推荐阅读