日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python好多模块和c相识_快速实现python c扩展模块

發布時間:2024/10/8 python 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python好多模块和c相识_快速实现python c扩展模块 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 ?python擴展模塊的組成

在python中,對于一些和系統相關的模塊或者對性能要求很高的模塊,通常會把這個模塊C化。擴展模塊中主要包含下面幾個部分:

init函數,函數名為:init+模塊名,這個函數負責初始化模塊,包括設置模塊中的方法、對象和其它相關數據的初始化。這個函數是必須的,在腳本中第一次導入這個模塊的時候,會先執行這個方法。

定義模塊方法描述表,它是一個static類型的PyMethodDef數據結構,用來描述模塊中定義的方法。

C函數定義,這些函數是方法描述表中方法的具體實現。

如果模塊中定義了類,那么還要定義類方法描述表和對象類型。

2 ?實現python擴展模塊實例

當然,有了上面的組成部分,你還是不知道怎么實現一個模塊,下面就用官方的一個例子來演示怎么實現一個python擴展模塊,這個擴展模塊用來實現在python中執行命令行命令。

// spam.c

1 #include "Python.h"

2

3 static PyObject *SpamError;4

5 static PyObject *

6 spam_system(PyObject *self, PyObject *args)7 {8 const char *command;9 intsts;10

11 if (!PyArg_ParseTuple(args, "s", &command))12 returnNULL;13 sts =system(command);14 if (sts < 0) {15 PyErr_SetString(SpamError, "System command failed");16 returnNULL;17 }18 returnPyLong_FromLong(sts);19 }20

21 static PyMethodDef SpamMethods[] ={22 {"system", spam_system, METH_VARARGS,23 "Execute a shell command."},24 {NULL, NULL, 0, NULL} /*Sentinel*/

25 };26

27 PyMODINIT_FUNC28 initspam(void)29 {30 PyObject *m;31

32 m = Py_InitModule("spam", SpamMethods);33 if (m ==NULL)34 return;35

36 SpamError = PyErr_NewException("spam.error", NULL, NULL);37 Py_INCREF(SpamError);38 PyModule_AddObject(m, "error", SpamError);39 }

上面的initspam是模塊的初始化函數,函數開始調用了Py_InitModule初始化了一個名為spam的模塊,模塊的方法描述表是SpamMethods,它描述了模塊有個名為system的方法,這個方法的c/c++實現是spam_system函數。從spam_system函數可以看到它就是調用system函數執行從python傳過來的命令。有了上面的代碼,我們怎樣在python中使用了?很簡單,先將上面代碼編譯成動態鏈接庫,然后直接在python中用import語句導入這個模塊就可以用了。在Windows下的用vs編譯就行,不過在vs建立了dll工程后,需要設置下工程的屬性,目的是設置python擴展涉及到的頭文件路徑和動態庫。具體設置如下:先在VC++目錄中設置include和lib路徑,然后在鏈接器的附加依賴項中添加python27.lib庫。

設置好后直接編譯就可以了,將編譯生成的dll文件后綴名改成pyd,然后就可以在python中直接用import導入這個模塊了。是不是非常的簡單!!!!

3 ?實現python擴展模塊中定義類

上面的實現是在模塊中定義函數來實現執行命令行命令,我們也可以在模塊中定義類,然后用類的方法來執行這個命令。代碼如下:

// spam.c

1 #include "Python.h"

2

3 static PyObject *SpamError;4

5 static PyObject *

6 spam_system(PyObject *self, PyObject *args)7 {8 const char *command;9 intsts;10

11 if (!PyArg_ParseTuple(args, "s", &command))12 returnNULL;13 sts =system(command);14 if (sts < 0) {15 PyErr_SetString(SpamError, "System command failed");16 returnNULL;17 }18 returnPyLong_FromLong(sts);19 }20

21 static PyMethodDef SpamMethods[] ={22 {"system", spam_system, METH_VARARGS,23 "Execute a shell command."},24 {NULL, NULL, 0, NULL} /*Sentinel*/

25 };26

27 PyTypeObject *SpamType =NULL;28

29 PyMODINIT_FUNC30 initspam(void)31 {32 static PyTypeObject _SpamType ={33 PyObject_HEAD_INIT(NULL)34 0, //ob_size

35 "spam.Spam", //tp_name

36 sizeof(PyObject), //tp_basicsize

37 0, //tp_itemsize

38 0, //tp_dealloc

39 0, //tp_print

40 0, //tp_getattr

41 0, //tp_setattr

42 0, //tp_compare

43 0, //tp_repr

44 0, //tp_as_number

45 0, //tp_as_sequence

46 0, //tp_as_mapping

47 0, //tp_hash

48 0, //tp_call

49 0, //tp_str

50 0, //tp_getattro

51 0, //tp_setattro

52 0, //tp_as_buffer

53 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , //tp_flags

54 0, //tp_doc

55 0, //tp_traverse

56 0, //tp_clear

57 0, //tp_richcompare

58 0, //tp_weaklistoffset

59 0, //tp_iter

60 0, //tp_iternext

61 SpamMethods, //tp_methods

62 0, //tp_members

63 0, //tp_getset

64 0, //tp_base

65 0, //tp_dict

66 0, //tp_descr_get

67 0, //tp_descr_set

68 0, //tp_dictoffset

69 0, //tp_init

70 0, //tp_alloc

71 PyType_GenericNew, //tp_new

72 };73

74 PyObject *m;75

76 m = Py_InitModule("spam", NULL);77 if (m ==NULL)78 return;79 if (PyType_Ready(&_SpamType) < 0)80 return;81 SpamType = &_SpamType;82 Py_INCREF(SpamType);83 PyModule_AddObject(m, "Spam", (PyObject*)SpamType);84 SpamError = PyErr_NewException("spam.error", NULL, NULL);85 Py_INCREF(SpamError);86 PyModule_AddObject(m, "error", SpamError);87 }

上面的代碼與之前的代碼只是多了個Spam類的定義,使用的時候通過Spam的實例化對象來調用system函數。

4 ?Python/C API涉及的引用計數問題

通過上面的例子,是不是覺得寫python的C擴展模塊非常的簡單呢?其實不然,主要是python中有個引用計數問題,在寫擴展模塊的時候必須非常小心的處理,否則很有容易導致內存泄露。根據python官方的定義,在Python/C API中,引用計數的行為被歸納為三種:new reference、borrow reference和steal reference,前兩種用于描述返回PyObject*類型的函數對返回的這個對象的引用計數的行為;后一種用于將一個PyObject*類型傳入函數后,函數對這個對象的引用計數的行為。new referenc表示函數將這個對象引用的所有權轉交給函數調用者了,由函數的調用者來管理這個引進的計數,也就是說調用者不用這個引用的時候必須顯示的調用?Py_DECREF()或者Py_XDECREF()來釋放這個引用,典型的函數是PyObject_、PyNumber_、PySequence_和PyMapping_;borrow reference與new reference剛好相反,表示函數的調用者只管用這個引用,不用關心它的引用計數,用完了也不用顯示調用Py_DECREF()或者Py_XDECREF()來釋放這個引用,典型的函數是PyList_GetItem、PyTuple_GetItem;steal reference表示函數內部只會使用這個引用,不會調用Py_INCREF來增加這個引用的引用計數,相當于“偷了”被調用者的一個引用計數,典型的函數是PyList_SetItem()和PyTuple_SetItem()。因此,在編寫C擴展的時,如果遇到某個Python/C API不確定是哪種reference的時候,建議查下官方文檔,文檔中會明確的說明這個函數是哪類reference(如下圖所示),這樣能大大減少引用計數的問題。

5 ?參考

總結

以上是生活随笔為你收集整理的python好多模块和c相识_快速实现python c扩展模块的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲a√| 丁香婷婷激情 | 偷拍老头老太高潮抽搐 | 超碰91人人 | 久久一热 | 中文字幕在线播放av | 天天操天天射天天舔 | 日韩欧美在线免费观看 | 中文文字幕文字幕高清 | 亚洲精选av | 人人爱人人草 | 成年人www| 99国产免费| 欧美日本高清 | 秋霞av在线| 精品国偷自产国产一区 | 日韩一区二区影视 | 国内自拍视频网站 | 1000部av| 日韩视频在线免费播放 | 国产美女福利在线 | 尤物网址在线观看 | www.久久伊人| 羞羞羞网站| 又黄又爽在线观看 | 国产一区二区三区四区五区在线 | 日韩一区在线观看视频 | 亚洲奶汁xxxx哺乳期 | 中文字幕第一区综合 | 无码人妻精品一区二区三区9厂 | www.爱色av.com| 人妻无码中文字幕 | 91精品国产一区二区三区蜜臀 | 欧美日韩成人在线视频 | av不卡中文字幕 | 99re超碰 | 欧美黄色三级 | 四虎色 | 成人福利视频在线观看 | 91视频免费看片 | 嫩草视频在线观看视频 | 自拍偷拍激情视频 | 欧美日韩亚洲综合 | 国产香蕉一区二区三区 | 亚洲片国产一区一级在线观看 | 成片免费观看 | 日本久久一区二区 | 蜜臀av在线观看 | 国产精品福利电影 | 国产精品第十页 | 国产一区欧美日韩 | 国产女18毛片多18精品 | 2一3sex性hd | 欧美区在线观看 | 黄色精品网站 | 欧美成人精品一区 | www.亚洲欧美 | 一本色道无码道dvd在线观看 | 黄色av免费观看 | 亚洲va天堂va欧美ⅴa在线 | 五月天综合婷婷 | 成人v| 亚洲色婷婷一区二区三区 | 天天爽夜夜爽视频 | 日韩毛片在线播放 | 欧美香蕉 | 午夜视频福利网站 | 影音先锋成人资源站 | 亚洲不卡影院 | av网站免费大全 | 色婷在线 | av毛片在线看 | 韩国视频一区二区 | 免费精品无码AV片在线观看黄 | 自拍偷拍第5页 | 亚洲v日本 | 日韩精品电影一区 | 成人在线欧美 | 99九九热 | 九九热精 | 在线观看国产一级片 | 亚洲国产区 | 狠狠丁香 | 精品96久久久久久中文字幕无 | 日韩一级成人 | 乱亲女h秽乱长久久久 | 鲁一鲁色一色 | 秋霞av鲁丝片一区二区 | 欧美精品久久久久久久 | 亚洲一卡二卡三卡 | 亚洲专区区免费 | 国产农村老头老太视频 | 18禁男女爽爽爽午夜网站免费 | 一级毛片aa | 日韩av电影网址 | 久久亚洲精品视频 | 狠狠干美女 | 国产成人愉拍精品久久 | 毛片毛片毛片毛片毛片毛片毛片 |