<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ### 導航 - [索引](../genindex.xhtml "總目錄") - [模塊](../py-modindex.xhtml "Python 模塊索引") | - [下一頁](curses.xhtml "Curses Programming with Python") | - [上一頁](pyporting.xhtml "將 Python 2 代碼遷移到 Python 3") | - ![](https://box.kancloud.cn/a721fc7ec672275e257bbbfde49a4d4e_16x16.png) - [Python](https://www.python.org/) ? - zh\_CN 3.7.3 [文檔](../index.xhtml) ? - [Python 常用指引](index.xhtml) ? - $('.inline-search').show(0); | # 將擴展模塊移植到 Python 3 作者Benjamin Peterson 摘要 盡管更改 C-API 并不是 Python 3 的目標之一,但許多 Python 級別的更改使得 Python 2 的 API 無法完整實現。實際上,一些變化如 [`int()`](../library/functions.xhtml#int "int") 和 `long()` 的統一在 C 級別更明顯。本文檔致力于記錄不兼容性以及如何解決這些問題。 ## 條件編譯 僅編譯 Python 3 的一些代碼的最簡單方法是檢查 `PY_MAJOR_VERSION` 是否大于或等于3。 ``` #if PY_MAJOR_VERSION >= 3 #define IS_PY3K #endif ``` 不存在的 API 函數可以在條件塊中別名為它們的等價物。 ## 對象API的更改 Python 3 將一些具有類似功能的類型合并在一起,同時干凈地分離了其他類型。 ### str/unicode 統一 Python 3 的 [`str()`](../library/stdtypes.xhtml#str "str") 類型相當于 Python 2 的 `unicode()` ; C函數被稱為 `PyUnicode_*` 。舊的 8 位字符串類型變為 [`bytes()`](../library/stdtypes.xhtml#bytes "bytes") ,其中 C 函數稱為 `PyBytes_*` 。 Python 2.6 及更高版本提供了一個兼容性頭文件 `bytesobject.h` ,將 `PyBytes` 名稱映射到 `PyString` 。 為了保持與 Python 3 的最佳兼容性, `PyUnicode` 應該用于文本數據,并且 `PyBytes` 用于二進制數據。同樣重要的是要記住 `pyBytes` 和 Python 3中的 `PyUnicode` 不可互換,如 `PyString` 和 `PyUnicode` 在 Python 2 以下中示例顯示了以下方面的最佳實踐 `PyUnicode` 、 `PyString` 和 `PyBytes` 。: ``` #include "stdlib.h" #include "Python.h" #include "bytesobject.h" /* text example */ static PyObject * say_hello(PyObject *self, PyObject *args) { PyObject *name, *result; if (!PyArg_ParseTuple(args, "U:say_hello", &name)) return NULL; result = PyUnicode_FromFormat("Hello, %S!", name); return result; } /* just a forward */ static char * do_encode(PyObject *); /* bytes example */ static PyObject * encode_object(PyObject *self, PyObject *args) { char *encoded; PyObject *result, *myobj; if (!PyArg_ParseTuple(args, "O:encode_object", &myobj)) return NULL; encoded = do_encode(myobj); if (encoded == NULL) return NULL; result = PyBytes_FromString(encoded); free(encoded); return result; } ``` ### long/int 統一 Python 3 只有一個整數類型, [`int()`](../library/functions.xhtml#int "int") 。但它實際上對應于Python 2 `long()` 類型 —— 刪除了 Python 2 中使用的 [`int()`](../library/functions.xhtml#int "int") 類型。在 C-API 中, `PyInt_*` 函數被它們等價的 `PyLong_*` 替換。 ## 模塊初始化和狀態 Python 3 有一個改進的擴展模塊初始化系統。(參見 [**PEP 3121**](https://www.python.org/dev/peps/pep-3121) \[https://www.python.org/dev/peps/pep-3121\] 。)而不是將模塊狀態存儲在全局變量中,它們應該存儲在特定于解釋器的結構中。創建在 Python 2 和 Python 3 中正確運行的模塊非常棘手。以下簡單示例演示了如何操作。: ``` #include "Python.h" struct module_state { PyObject *error; }; #if PY_MAJOR_VERSION >= 3 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) #else #define GETSTATE(m) (&_state) static struct module_state _state; #endif static PyObject * error_out(PyObject *m) { struct module_state *st = GETSTATE(m); PyErr_SetString(st->error, "something bad happened"); return NULL; } static PyMethodDef myextension_methods[] = { {"error_out", (PyCFunction)error_out, METH_NOARGS, NULL}, {NULL, NULL} }; #if PY_MAJOR_VERSION >= 3 static int myextension_traverse(PyObject *m, visitproc visit, void *arg) { Py_VISIT(GETSTATE(m)->error); return 0; } static int myextension_clear(PyObject *m) { Py_CLEAR(GETSTATE(m)->error); return 0; } static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "myextension", NULL, sizeof(struct module_state), myextension_methods, NULL, myextension_traverse, myextension_clear, NULL }; #define INITERROR return NULL PyMODINIT_FUNC PyInit_myextension(void) #else #define INITERROR return void initmyextension(void) #endif { #if PY_MAJOR_VERSION >= 3 PyObject *module = PyModule_Create(&moduledef); #else PyObject *module = Py_InitModule("myextension", myextension_methods); #endif if (module == NULL) INITERROR; struct module_state *st = GETSTATE(module); st->error = PyErr_NewException("myextension.Error", NULL, NULL); if (st->error == NULL) { Py_DECREF(module); INITERROR; } #if PY_MAJOR_VERSION >= 3 return module; #endif } ``` ## CObject 替換為 Capsule `Capsule` 對象是在 Python 3.1 和 2.7 中引入的,用于替換 `CObject` 。 CObject 是有用的,但是 `CObject` API 是有問題的:它不允許區分有效的 CObject ,這導致不匹配的 CObject 使解釋器崩潰,并且它的一些 API 依賴于 C 中的未定義行為。有關 Capsule 背后的基本原理的進一步閱讀,請參閱 [bpo-5630](https://bugs.python.org/issue5630) \[https://bugs.python.org/issue5630\] 。) 如果你當前正在使用 CObject ,并且想要遷移到 3.1 或更高版本,則需要切換到 Capsules 。 `CObject` 在 3.1 和 2.7 中已棄用,在 Python 3.2 中已完全刪除。如果你只支持 2.7 或 3.1 及以上,你可以簡單地切換到 `Capsule` 。如果你需要支持 Python 3.0 或早于 2.7 的 Python 版本,則必須同時支持 CObject 和 Capsule 。(請注意,不再支持 Python 3.0 ,不建議將其用于生產用途。) 以下示例頭文件 `capsulethunk.h` 可以為你解決問題。只需針對 `Capsule` API 編寫代碼,并在以下文件后包含此頭文件 `Python.h` 。你的代碼將自動在帶有 Capsule 的 Python 版本中使用 Capsules ,并在 Capsule 不可用時切換到 CObjects 。 `capsulethunk.h` 使用 CObject 模擬 Capsules 。 但是, `CObject` 沒有提供存儲膠囊的“名稱”的地方。因此,模擬 `Capsule` 對象由 `capsulethunk.h` 創建,其行為與真實 Capsule 略有不同。特別地: > - 傳遞給 [`PyCapsule_New()`](../c-api/capsule.xhtml#c.PyCapsule_New "PyCapsule_New") 的 name 參數被忽略。 > - 傳入以下命令的 name 參數 [`PyCapsule_IsValid()`](../c-api/capsule.xhtml#c.PyCapsule_IsValid "PyCapsule_IsValid") 和 [`PyCapsule_GetPointer()`](../c-api/capsule.xhtml#c.PyCapsule_GetPointer "PyCapsule_GetPointer") 被忽略,并且不執行錯誤檢查。 > - [`PyCapsule_GetName()`](../c-api/capsule.xhtml#c.PyCapsule_GetName "PyCapsule_GetName") 總是返回 NULL 。 > - [`PyCapsule_SetName()`](../c-api/capsule.xhtml#c.PyCapsule_SetName "PyCapsule_SetName") 總是引發異常并返回失敗。(由于無法在 CObject 中存儲名稱,因此 [`PyCapsule_SetName()`](../c-api/capsule.xhtml#c.PyCapsule_SetName "PyCapsule_SetName") 的明顯失敗被認為優于靜默失敗。如果這樣不方便,請隨意根據需要修改本地副本。) 你可以在 Python 源代碼分發中的 [Doc/includes/capsulethunk.h](https://github.com/python/cpython/tree/3.7/Doc/includes/capsulethunk.h) \[https://github.com/python/cpython/tree/3.7/Doc/includes/capsulethunk.h\] 找到 `capsulethunk.h` 。為方便起見,我們還將其包含在此處: ``` #ifndef __CAPSULETHUNK_H #define __CAPSULETHUNK_H #if ( (PY_VERSION_HEX < 0x02070000) \ || ((PY_VERSION_HEX >= 0x03000000) \ && (PY_VERSION_HEX < 0x03010000)) ) #define __PyCapsule_GetField(capsule, field, default_value) \ ( PyCapsule_CheckExact(capsule) \ ? (((PyCObject *)capsule)->field) \ : (default_value) \ ) \ #define __PyCapsule_SetField(capsule, field, value) \ ( PyCapsule_CheckExact(capsule) \ ? (((PyCObject *)capsule)->field = value), 1 \ : 0 \ ) \ #define PyCapsule_Type PyCObject_Type #define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) #define PyCapsule_IsValid(capsule, name) (PyCObject_Check(capsule)) #define PyCapsule_New(pointer, name, destructor) \ (PyCObject_FromVoidPtr(pointer, destructor)) #define PyCapsule_GetPointer(capsule, name) \ (PyCObject_AsVoidPtr(capsule)) /* Don't call PyCObject_SetPointer here, it fails if there's a destructor */ #define PyCapsule_SetPointer(capsule, pointer) \ __PyCapsule_SetField(capsule, cobject, pointer) #define PyCapsule_GetDestructor(capsule) \ __PyCapsule_GetField(capsule, destructor) #define PyCapsule_SetDestructor(capsule, dtor) \ __PyCapsule_SetField(capsule, destructor, dtor) /* * Sorry, there's simply no place * to store a Capsule "name" in a CObject. */ #define PyCapsule_GetName(capsule) NULL static int PyCapsule_SetName(PyObject *capsule, const char *unused) { unused = unused; PyErr_SetString(PyExc_NotImplementedError, "can't use PyCapsule_SetName with CObjects"); return 1; } #define PyCapsule_GetContext(capsule) \ __PyCapsule_GetField(capsule, descr) #define PyCapsule_SetContext(capsule, context) \ __PyCapsule_SetField(capsule, descr, context) static void * PyCapsule_Import(const char *name, int no_block) { PyObject *object = NULL; void *return_value = NULL; char *trace; size_t name_length = (strlen(name) + 1) * sizeof(char); char *name_dup = (char *)PyMem_MALLOC(name_length); if (!name_dup) { return NULL; } memcpy(name_dup, name, name_length); trace = name_dup; while (trace) { char *dot = strchr(trace, '.'); if (dot) { *dot++ = '\0'; } if (object == NULL) { if (no_block) { object = PyImport_ImportModuleNoBlock(trace); } else { object = PyImport_ImportModule(trace); if (!object) { PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not " "import module \"%s\"", trace); } } } else { PyObject *object2 = PyObject_GetAttrString(object, trace); Py_DECREF(object); object = object2; } if (!object) { goto EXIT; } trace = dot; } if (PyCObject_Check(object)) { PyCObject *cobject = (PyCObject *)object; return_value = cobject->cobject; } else { PyErr_Format(PyExc_AttributeError, "PyCapsule_Import \"%s\" is not valid", name); } EXIT: Py_XDECREF(object); if (name_dup) { PyMem_FREE(name_dup); } return return_value; } #endif /* #if PY_VERSION_HEX < 0x02070000 */ #endif /* __CAPSULETHUNK_H */ ``` ## 其他選項 如果你正在編寫新的擴展模塊,你可能會考慮 [Cython](http://cython.org/) \[http://cython.org/\] 。 它將類似 Python 的語言轉換為 C 。它創建的擴展模塊與 Python 3 和 Python 2 兼容。 ### 導航 - [索引](../genindex.xhtml "總目錄") - [模塊](../py-modindex.xhtml "Python 模塊索引") | - [下一頁](curses.xhtml "Curses Programming with Python") | - [上一頁](pyporting.xhtml "將 Python 2 代碼遷移到 Python 3") | - ![](https://box.kancloud.cn/a721fc7ec672275e257bbbfde49a4d4e_16x16.png) - [Python](https://www.python.org/) ? - zh\_CN 3.7.3 [文檔](../index.xhtml) ? - [Python 常用指引](index.xhtml) ? - $('.inline-search').show(0); | ? [版權所有](../copyright.xhtml) 2001-2019, Python Software Foundation. Python 軟件基金會是一個非盈利組織。 [請捐助。](https://www.python.org/psf/donations/) 最后更新于 5月 21, 2019. [發現了問題](../bugs.xhtml)? 使用[Sphinx](http://sphinx.pocoo.org/)1.8.4 創建。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看