Python C API 解读随笔 ----简介篇

读别人的代码,看到C++和Python接口感觉自己还欠缺太多,有些地方不知道如何实现调用的,得补补这块知识。

此篇仅为随笔,记录我觉得是要点的内容,章节号与官方文档相同,方便查找。


简介

1.Python与C++有两种方法交互,一种为C++程序封装Python接口,这样可以用Python调用C+模块。第二种,在C++程序上嵌入Python支持,这一种比较高级,Python C API推荐熟悉了第一种,再做第二种。

头文件

2.再写这种模块时,需要首先include“Python.h”(“Python.h”中包含了<stdio.h><string.h><errno.h><limits.h>,<assert.h> and <stdlib.h>),并且Python.h中定义了一些可能会在某些系统上和标准头文件预处理变量,所以首先包含Python.h。

3.在Python.h看定义的宏都以Py或_Py开头,其中_Py是Python解释器使用的,用户不要用它。用户也不要定义以Py或_Py开头的宏,防止和以后版本的Python宏冲突。

4.在包含Python头文件时,要到Python头文件那一级,不要用#include<Pythonx.y/Python.h>,这在不同的平台上可能会出错。因为Python.h包含的文件不同。

对象、类型和引用计数

5.大多数的Python/C API 函数有一到多个参数和一个PyObject*的返回值。这个返回值指向一个Python变量。由于大多数的Python obects建立在堆上(局部变量在函数结尾会被删除),所以不要建立局部变量(像PyObject a)和静态变量,除了PyTypeObject类型的。

引用计数

6.Python中每一个对象都是有引用计数的,一旦检查这个对象的引用计数为0,就会删除这个Python对象。增加和删除引用可以用 Py_INCREF()Py_DECREF() 实现。这两个函数很容易操作失误,所以官方文档中推荐使用封装好的对象(以PyObject_PyNumber_PySequence_ or PyMapping_开头)。

引用计数细节

7.Python对象的引用计数不依赖于拥有者(owner),只与计数的值有关,这和java、c#一样。
8.Python处理引用计数有两种方式,正常模式和借用模式(原文steal)。正常模式,在用Python函数引用一个对象时会给这个被引用对象加引用计数(像PySequence_GetItem())。借用模式的话,只获得引用,不增加计数,这样的函数比较少,像PyList_SetItem()PyTuple_SetItem()同时,官方文档也不推荐直接操作引用计数。

异常

9.Python编程者只需要在可能出错的地方检查下异常,即使没检查,出错之后,Python的异常机制也会报告。c的话就需要用户自己细致地检查每一个错误。c语言中一旦某个函数出现异常,就需要去除函数中产生的每个引用,并返回一个错误说明,没有说明,通常是NULL或-1.很少函数返回true或false。非常少函数返回不确定的错误提示或者需要用PyErr_Occurred()检查当前错误值。
10.异常是以线程为分类抛出的。PyErr_Occurred()可以用来检查具体错误信息。PyErr_SetString()是最常用的设置异常信息的函数, PyErr_Clear() 用来清除异常信息。
11.异常包括三方面信息:异常类型、异常值和堆栈信息。Python的sys.exc_typesys.exc_value, and sys.exc_traceback也可以访问这三项信息。Python有try...catch机制,c语言没有,所以在c语言中的错误信息(通常以整数表示)向上传递直到Python 解析器可以发现时,Python的这三个变量才可以获得异常信息。
12.从Python1.5开始,最安全的获得异常的方法是sys.exc_info()。
13.函数A调用函数B,而函数B抛出了异常,这时候函数A应该清除自己拥有的所有引用信息,并向上传递函数B的异常信息。函数A这时不能建立新的异常,因为这会清除函数B的异常信息。


嵌入Python

14.和写Python的扩展模块不同,嵌入Python时要考虑Python解释器的初始化和结束。
15.Py_Initialize()是初始化函数。这个函数会初始化Python用到的一些模块,包括__builtin____main__sys, 和 exceptions这一过程中也会初始化sys.path。
16.Py_Initialize()不会初始化参数列表。初始化之后,参数会被PySys_SetArgvEx(argc,argv, updatepath)设置。
17.Python初始化时会假定Python的各项目录结构是固定的。极特殊情况下,在初始化时会搜索lib/PythonX.Y(环境变量里用的,指定python解释器位置)。例如,如果Python解释器在/usr/local/bin/python目录下找到,Python会假定python库在/usr/local/lib/pythonX.Y,这种搜索会在PATH中找不到python解释器和情况下使用。
18.用户可通过设置PYTHONHOME或通过设置PYTHONPATH在标准目录前插入自定义目录的方法修改Python目录。
19.被嵌入Python的程序可能通过Py_SetProgramName(file)设置搜索,但这一操作可以通过第18条中的方法覆盖。
20.被嵌入程序可能通过Py_GetPath()Py_GetPrefix()Py_GetExecPrefix(), and Py_GetProgramFullPath()获得Python的详细情况(这些变量在Modules/getpath.c定义)
21.当程序不再需要Python时,可以使用Py_Finalize()收回Python所占用的内存,但不能完全清除Python所使用的内存,例如扩展模块所占用的内存这时不能能收回。Py_IsInitialized()可以查询Python是否在运行。

编译带debug信息的python

这一节用不到,暂时不翻译了。

你可能感兴趣的:(c,api,python)